feat: HackerOne scope ingestion into a ScopeGuard#19
Merged
Conversation
Adds a HackerOne client that pulls a program's structured scopes and builds a
ScopeGuard from the host assets eligible for submission, so a program's
authoritative scope flows straight into the scanner (and its audit trail)
instead of a hand-typed allowlist.
- HackerOneClient.structured_scopes(handle): reads
/v1/hackers/programs/{handle}/structured_scopes with HTTP Basic auth
(H1_USERNAME / H1_API_TOKEN), following pagination.
- HackerOneClient.scope_guard(handle, *, bounty_only, allow_subdomains): maps
URL / WILDCARD / DOMAIN assets to a ScopeGuard; skips submission-ineligible
assets and non-host asset types (mobile apps, CIDRs, ...).
- Fail-closed on missing credentials, auth rejection, 404, non-200, bad JSON,
and invalid handles. HTTP layer is injectable (typed Protocol) so tests run
against a mocked API with no network.
Pattern adapted from shuvonsec/claude-bug-bounty (MIT) mcp/hackerone-mcp, moved
from the public GraphQL endpoint to the authenticated REST scopes API and shaped
to feed this project's ScopeGuard + AuditLog.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Pulls a HackerOne program's structured scopes and builds a
ScopeGuardfrom them, so a program's authoritative in-scope assets flow straight into the scanner — and its audit trail (#17) — instead of a hand-typed allowlist.API
HackerOneClient.structured_scopes(handle)— reads/v1/hackers/programs/{handle}/structured_scopeswith HTTP Basic auth (H1_USERNAME/H1_API_TOKEN), following pagination.HackerOneClient.scope_guard(handle, *, bounty_only=False, allow_subdomains=True)— mapsURL/WILDCARD/DOMAINassets to aScopeGuard; skips submission-ineligible assets and non-host asset types (mobile apps, CIDRs, source repos).Safety
Fail-closed on every edge: missing credentials, auth rejection (401/403), unknown program (404), non-200, invalid JSON, and malformed/path-injecting handles all raise a typed
HackerOneError. The HTTP layer is an injectable typedProtocol(same idiom asbrain.py), so tests run against a mocked API with no network and no real token.This is the loop closer
It ties the two prior borrows together: H1 scope →
ScopeGuard→SecurityScanner→AuditLog. Scope is no longer hand-maintained; it comes from the authoritative source, and every request is checked and logged against it.Tests
tests/test_hackerone.py(injected fake session): scope parsing + auth passthrough, in-scope allow / out-of-scope deny / ineligible filtered / non-host skipped,bounty_only, pagination, missing-credentials, HTTP errors (401/403/404/500), and invalid-handle rejection. Verified locally against the real client with a stubbed transport.I did not add an
__init__export (to avoid colliding with #17's__init__change) — import viafrom bugbounty_ctf.hackerone import HackerOneClient. Can add the export once #17 merges.Live-auth step for you
Tests mock the API. To confirm the real path: create an API token at https://hackerone.com/settings/api_token/edit,
export H1_USERNAME=... H1_API_TOKEN=..., thenHackerOneClient().scope_guard("<a-program-you're-invited-to>")and eyeball the allowlist.🤖 Generated with Claude Code