[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F46BS3YEVNF2TPD38BEFE2":3,"skill-same:01M6F46BS3YEVNF2TPD38BEFE2":76},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":58,"ownerHtmlUrl":59,"ownerBlogUrl":6,"ownerDescription":60,"updatedAt":61,"install":62,"resources":75},"01M6F46BS3YEVNF2TPD38BEFE2","github-evidence-kit",null,"Generate, export, load, and verify forensic evidence from GitHub sources. Use when creating verifiable evidence objects from GitHub API, GH Archive, Wayback Machine, local git repositories, or security vendor reports. Handles evidence storage, querying, and re-verification against original sources.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fgadievron\u002Fraptor\u002Fgithub-evidence-kit\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"github evidence kit","evidence","github","use","re","machine","sources","local","objects","reports","export","gh","archive","api","osint","verification","git","generate","storage","security","2026-11-10 10:12:30",false,"---\nname: github-evidence-kit\ndescription: Generate, export, load, and verify forensic evidence from GitHub sources. Use when creating verifiable evidence objects from GitHub API, GH Archive, Wayback Machine, local git repositories, or security vendor reports. Handles evidence storage, querying, and re-verification against original sources.\nversion: 2.0\nauthor: mbrg\ntags:\n  - github\n  - forensics\n  - osint\n  - evidence\n  - verification\n  - git\n---\n\n# GH Evidence Kit\n\n**Purpose**: Create, store, and verify forensic evidence from GitHub-related public sources and local git repositories.\n\n## When to Use This Skill\n\n- Creating verifiable evidence objects from GitHub activity\n- **Local git forensics** - analyzing cloned repositories, dangling commits, reflog\n- Exporting evidence collections to JSON for sharing\u002Farchival\n- Loading and re-verifying previously collected evidence\n- Recovering deleted GitHub content (issues, PRs, commits) from GH Archive\n- Tracking IOCs (Indicators of Compromise) with source verification\n\n## Quick Start\n\n```python\nfrom src.collectors import GitHubAPICollector, LocalGitCollector, GHArchiveCollector\nfrom src import EvidenceStore\n\n# Create collectors for different sources\ngithub = GitHubAPICollector()\nlocal = LocalGitCollector(\"\u002Fpath\u002Fto\u002Frepo\")\narchive = GHArchiveCollector()\n\n# Collect evidence from GitHub API\ncommit = github.collect_commit(\"aws\", \"aws-toolkit-vscode\", \"678851b...\")\npr = github.collect_pull_request(\"aws\", \"aws-toolkit-vscode\", 7710)\n\n# Collect evidence from local git (first-class forensic source)\nlocal_commit = local.collect_commit(\"HEAD\")\ndangling = local.collect_dangling_commits()  # Forensic gold!\n\n# Store and export\nstore = EvidenceStore()\nstore.add(commit)\nstore.add(pr)\nstore.add(local_commit)\nstore.add_all(dangling)\nstore.save(\"evidence.json\")\n\n# Verify all evidence against original sources\nis_valid, errors = store.verify_all()\n```\n\n## Collectors\n\n### GitHubAPICollector\n\nCollects evidence from the live GitHub API.\n\n```python\nfrom src.collectors import GitHubAPICollector\n\ncollector = GitHubAPICollector()\n```\n\n| Method | Returns |\n|--------|---------|\n| `collect_commit(owner, repo, sha)` | CommitObservation |\n| `collect_issue(owner, repo, number)` | IssueObservation |\n| `collect_pull_request(owner, repo, number)` | IssueObservation |\n| `collect_file(owner, repo, path, ref)` | FileObservation |\n| `collect_branch(owner, repo, branch_name)` | BranchObservation |\n| `collect_tag(owner, repo, tag_name)` | TagObservation |\n| `collect_release(owner, repo, tag_name)` | ReleaseObservation |\n| `collect_forks(owner, repo)` | list[ForkObservation] |\n\n### LocalGitCollector (First-Class Forensics)\n\nCollects evidence from local git repositories. Essential for forensic analysis of cloned repos.\n\n```python\nfrom src.collectors import LocalGitCollector\n\ncollector = LocalGitCollector(\"\u002Fpath\u002Fto\u002Fcloned\u002Frepo\")\n\n# Collect a specific commit\ncommit = collector.collect_commit(\"HEAD\")\ncommit = collector.collect_commit(\"abc123\")\n\n# Find dangling commits (not reachable from any ref)\n# This is forensic gold - reveals force-pushed or deleted commits!\ndangling = collector.collect_dangling_commits()\nfor commit in dangling:\n    print(f\"Found dangling: {commit.sha[:8]} - {commit.message}\")\n```\n\n| Method | Returns |\n|--------|---------|\n| `collect_commit(sha)` | CommitObservation |\n| `collect_dangling_commits()` | list[CommitObservation] |\n\n### GHArchiveCollector\n\nCollects and recovers evidence from GH Archive (BigQuery). Requires credentials.\n\n```python\nfrom src.collectors import GHArchiveCollector\n\ncollector = GHArchiveCollector()\n\n# Query events by timestamp (YYYYMMDDHHMM format)\nevents = collector.collect_events(\n    timestamp=\"202507132037\",\n    repo=\"aws\u002Faws-toolkit-vscode\"\n)\n\n# Recover deleted content\ndeleted_issue = collector.recover_issue(\"aws\u002Faws-toolkit-vscode\", 123, \"2025-07-13T20:30:24Z\")\ndeleted_pr = collector.recover_pr(\"aws\u002Faws-toolkit-vscode\", 7710, \"2025-07-13T20:30:24Z\")\ndeleted_commit = collector.recover_commit(\"aws\u002Faws-toolkit-vscode\", \"678851b\", \"2025-07-13T20:30:24Z\")\nforce_pushed = collector.recover_force_push(\"aws\u002Faws-toolkit-vscode\", \"2025-07-13T20:30:24Z\")\n```\n\n| Method | Returns |\n|--------|---------|\n| `collect_events(timestamp, repo, actor, event_type)` | list[Event] |\n| `recover_issue(repo, number, timestamp)` | IssueObservation |\n| `recover_pr(repo, number, timestamp)` | IssueObservation |\n| `recover_commit(repo, sha, timestamp)` | CommitObservation |\n| `recover_force_push(repo, timestamp)` | CommitObservation |\n\n### WaybackCollector\n\nCollects archived snapshots from the Wayback Machine.\n\n```python\nfrom src.collectors import WaybackCollector\n\ncollector = WaybackCollector()\n\n# Get all snapshots for a URL\nsnapshots = collector.collect_snapshots(\"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\")\n\n# With date filtering\nsnapshots = collector.collect_snapshots(\n    \"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\",\n    from_date=\"20250101\",\n    to_date=\"20250731\"\n)\n\n# Fetch actual content of a snapshot\ncontent = collector.collect_snapshot_content(\n    \"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\",\n    \"20250713203024\"  # YYYYMMDDHHMMSS format\n)\n```\n\n## Verification\n\nVerification is separated from data collection. Use `ConsistencyVerifier` to validate evidence against original sources.\n\n```python\nfrom src.verifiers import ConsistencyVerifier\n\nverifier = ConsistencyVerifier()\n\n# Verify single evidence\nresult = verifier.verify(commit)\nif not result.is_valid:\n    print(f\"Errors: {result.errors}\")\n\n# Verify multiple\nresult = verifier.verify_all([commit, pr, issue])\n```\n\nOr use the convenience method on `EvidenceStore`:\n\n```python\nstore = EvidenceStore()\nstore.add_all([commit, pr, issue])\nis_valid, errors = store.verify_all()\n```\n\n## EvidenceStore\n\nStore, query, and export evidence collections.\n\n```python\nfrom src import EvidenceStore\nfrom datetime import datetime\n\nstore = EvidenceStore()\n\n# Add evidence\nstore.add(commit)\nstore.add_all([pr, issue, ioc])\n\n# Query\ncommits = store.filter(observation_type=\"commit\")\nrecent = store.filter(after=datetime(2025, 7, 1))\nfrom_github = store.filter(source=\"github\")\nfrom_git = store.filter(source=\"git\")\nrepo_events = store.filter(repo=\"aws\u002Faws-toolkit-vscode\")\n\n# Export\u002FImport\nstore.save(\"evidence.json\")\nstore = EvidenceStore.load(\"evidence.json\")\n\n# Summary\nprint(store.summary())\n# {'total': 5, 'events': {...}, 'observations': {...}, 'by_source': {...}}\n\n# Verify all against sources\nis_valid, errors = store.verify_all()\n```\n\n## Loading Evidence from JSON\n\n```python\nfrom src import load_evidence_from_json\nimport json\n\nwith open(\"evidence.json\") as f:\n    data = json.load(f)\n\nfor item in data:\n    evidence = load_evidence_from_json(item)\n    # Evidence is now a typed Pydantic model\n```\n\n## Evidence Types\n\n### Events (from GH Archive)\n\nAll 12 GitHub event types are supported:\n\n| Type | Description |\n|------|-------------|\n| PushEvent | Commits pushed |\n| PullRequestEvent | PR opened\u002Fclosed\u002Fmerged |\n| IssueEvent | Issue opened\u002Fclosed |\n| IssueCommentEvent | Comment on issue\u002FPR |\n| CreateEvent | Branch\u002Ftag created |\n| DeleteEvent | Branch\u002Ftag deleted |\n| ForkEvent | Repository forked |\n| WatchEvent | Repository starred |\n| MemberEvent | Collaborator added\u002Fremoved |\n| PublicEvent | Repository made public |\n| ReleaseEvent | Release published\u002Fcreated\u002Fdeleted |\n| WorkflowRunEvent | GitHub Actions run |\n\n### Observations (from GitHub API, Local Git, Wayback, Vendors)\n\n| Type | Description | Sources |\n|------|-------------|---------|\n| CommitObservation | Commit metadata and files | GitHub, Git, GH Archive |\n| IssueObservation | Issue or PR | GitHub, GH Archive |\n| FileObservation | File content at ref | GitHub |\n| BranchObservation | Branch HEAD | GitHub |\n| TagObservation | Tag target | GitHub |\n| ReleaseObservation | Release metadata | GitHub |\n| ForkObservation | Fork relationship | GitHub |\n| SnapshotObservation | Wayback snapshots | Wayback |\n| IOC | Indicator of Compromise | Vendor |\n| ArticleObservation | Security report\u002Fblog | Vendor |\n\n## IOC Types\n\n```python\nfrom src import EvidenceSource, IOCType\nfrom src.schema import IOC, VerificationInfo\nfrom pydantic import HttpUrl\nfrom datetime import datetime, timezone\n\n# IOCs are created directly as schema objects\nioc = IOC(\n    evidence_id=\"ioc-commit-sha-abc123\",\n    observed_when=datetime.now(timezone.utc),\n    observed_by=EvidenceSource.SECURITY_VENDOR,\n    observed_what=\"Malicious commit SHA found in vendor report\",\n    verification=VerificationInfo(\n        source=EvidenceSource.SECURITY_VENDOR,\n        url=HttpUrl(\"https:\u002F\u002Fvendor.com\u002Freport\")\n    ),\n    ioc_type=IOCType.COMMIT_SHA,\n    value=\"678851bbe9776228f55e0460e66a6167ac2a1685\",\n)\n```\n\nAvailable IOC types: `COMMIT_SHA`, `FILE_PATH`, `FILE_HASH`, `CODE_SNIPPET`, `EMAIL`, `USERNAME`, `REPOSITORY`, `TAG_NAME`, `BRANCH_NAME`, `WORKFLOW_NAME`, `IP_ADDRESS`, `DOMAIN`, `URL`, `API_KEY`, `SECRET`\n\n## Testing\n\n### Run Unit Tests\n\n```bash\ncd .claude\u002Fskills\u002Fgithub-forensics\u002Fgithub-evidence-kit\npip install -r requirements.txt\npytest tests\u002F -v --ignore=tests\u002Ftest_integration.py\n```\n\n### Run Integration Tests (Optional)\n\nIntegration tests hit real external services (GitHub API, BigQuery, vendor URLs):\n\n```bash\n# All integration tests\npytest tests\u002Ftest_integration.py -v -m integration\n\n# Skip integration tests in CI\npytest tests\u002F -v -m \"not integration\"\n```\n\n**Note**: GitHub API integration tests use 60 req\u002Fhr unauthenticated rate limit. BigQuery tests require credentials (see below).\n\n## GCP BigQuery Credentials (for GH Archive)\n\nGH Archive queries require Google Cloud BigQuery credentials. Two options:\n\n### Option 1: JSON File Path\n\n```bash\nexport GOOGLE_APPLICATION_CREDENTIALS=\u002Fpath\u002Fto\u002Fcredentials.json\n```\n\n### Option 2: JSON Content in Environment Variable\n\nUseful for `.env` files or CI secrets:\n\n```bash\nexport GOOGLE_APPLICATION_CREDENTIALS='{\"type\":\"service_account\",\"project_id\":\"...\",\"private_key\":\"...\"}'\n```\n\nThe client auto-detects JSON content vs file path.\n\n### Setup Steps\n\n1. Create a [Google Cloud Project](https:\u002F\u002Fconsole.cloud.google.com\u002F)\n2. Enable BigQuery API\n3. Create a Service Account with `BigQuery User` role\n4. Download JSON credentials\n5. Set `GOOGLE_APPLICATION_CREDENTIALS` env var\n\n**Free Tier**: 1 TB\u002Fmonth of BigQuery queries included.\n\n## Requirements\n\n```bash\npip install -r requirements.txt\n```\n\n- `pydantic` - Schema validation\n- `requests` - HTTP client\n- `google-cloud-bigquery` - GH Archive queries (optional)\n- `google-auth` - GCP authentication (optional)\n\n","# GH Evidence Kit\n\n**Purpose**: Create, store, and verify forensic evidence from GitHub-related public sources and local git repositories.\n\n## When to Use This Skill\n\n- Creating verifiable evidence objects from GitHub activity\n- **Local git forensics** - analyzing cloned repositories, dangling commits, reflog\n- Exporting evidence collections to JSON for sharing\u002Farchival\n- Loading and re-verifying previously collected evidence\n- Recovering deleted GitHub content (issues, PRs, commits) from GH Archive\n- Tracking IOCs (Indicators of Compromise) with source verification\n\n## Quick Start\n\n```python\nfrom src.collectors import GitHubAPICollector, LocalGitCollector, GHArchiveCollector\nfrom src import EvidenceStore\n\n# Create collectors for different sources\ngithub = GitHubAPICollector()\nlocal = LocalGitCollector(\"\u002Fpath\u002Fto\u002Frepo\")\narchive = GHArchiveCollector()\n\n# Collect evidence from GitHub API\ncommit = github.collect_commit(\"aws\", \"aws-toolkit-vscode\", \"678851b...\")\npr = github.collect_pull_request(\"aws\", \"aws-toolkit-vscode\", 7710)\n\n# Collect evidence from local git (first-class forensic source)\nlocal_commit = local.collect_commit(\"HEAD\")\ndangling = local.collect_dangling_commits()  # Forensic gold!\n\n# Store and export\nstore = EvidenceStore()\nstore.add(commit)\nstore.add(pr)\nstore.add(local_commit)\nstore.add_all(dangling)\nstore.save(\"evidence.json\")\n\n# Verify all evidence against original sources\nis_valid, errors = store.verify_all()\n```\n\n## Collectors\n\n### GitHubAPICollector\n\nCollects evidence from the live GitHub API.\n\n```python\nfrom src.collectors import GitHubAPICollector\n\ncollector = GitHubAPICollector()\n```\n\n| Method | Returns |\n|--------|---------|\n| `collect_commit(owner, repo, sha)` | CommitObservation |\n| `collect_issue(owner, repo, number)` | IssueObservation |\n| `collect_pull_request(owner, repo, number)` | IssueObservation |\n| `collect_file(owner, repo, path, ref)` | FileObservation |\n| `collect_branch(owner, repo, branch_name)` | BranchObservation |\n| `collect_tag(owner, repo, tag_name)` | TagObservation |\n| `collect_release(owner, repo, tag_name)` | ReleaseObservation |\n| `collect_forks(owner, repo)` | list[ForkObservation] |\n\n### LocalGitCollector (First-Class Forensics)\n\nCollects evidence from local git repositories. Essential for forensic analysis of cloned repos.\n\n```python\nfrom src.collectors import LocalGitCollector\n\ncollector = LocalGitCollector(\"\u002Fpath\u002Fto\u002Fcloned\u002Frepo\")\n\n# Collect a specific commit\ncommit = collector.collect_commit(\"HEAD\")\ncommit = collector.collect_commit(\"abc123\")\n\n# Find dangling commits (not reachable from any ref)\n# This is forensic gold - reveals force-pushed or deleted commits!\ndangling = collector.collect_dangling_commits()\nfor commit in dangling:\n    print(f\"Found dangling: {commit.sha[:8]} - {commit.message}\")\n```\n\n| Method | Returns |\n|--------|---------|\n| `collect_commit(sha)` | CommitObservation |\n| `collect_dangling_commits()` | list[CommitObservation] |\n\n### GHArchiveCollector\n\nCollects and recovers evidence from GH Archive (BigQuery). Requires credentials.\n\n```python\nfrom src.collectors import GHArchiveCollector\n\ncollector = GHArchiveCollector()\n\n# Query events by timestamp (YYYYMMDDHHMM format)\nevents = collector.collect_events(\n    timestamp=\"202507132037\",\n    repo=\"aws\u002Faws-toolkit-vscode\"\n)\n\n# Recover deleted content\ndeleted_issue = collector.recover_issue(\"aws\u002Faws-toolkit-vscode\", 123, \"2025-07-13T20:30:24Z\")\ndeleted_pr = collector.recover_pr(\"aws\u002Faws-toolkit-vscode\", 7710, \"2025-07-13T20:30:24Z\")\ndeleted_commit = collector.recover_commit(\"aws\u002Faws-toolkit-vscode\", \"678851b\", \"2025-07-13T20:30:24Z\")\nforce_pushed = collector.recover_force_push(\"aws\u002Faws-toolkit-vscode\", \"2025-07-13T20:30:24Z\")\n```\n\n| Method | Returns |\n|--------|---------|\n| `collect_events(timestamp, repo, actor, event_type)` | list[Event] |\n| `recover_issue(repo, number, timestamp)` | IssueObservation |\n| `recover_pr(repo, number, timestamp)` | IssueObservation |\n| `recover_commit(repo, sha, timestamp)` | CommitObservation |\n| `recover_force_push(repo, timestamp)` | CommitObservation |\n\n### WaybackCollector\n\nCollects archived snapshots from the Wayback Machine.\n\n```python\nfrom src.collectors import WaybackCollector\n\ncollector = WaybackCollector()\n\n# Get all snapshots for a URL\nsnapshots = collector.collect_snapshots(\"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\")\n\n# With date filtering\nsnapshots = collector.collect_snapshots(\n    \"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\",\n    from_date=\"20250101\",\n    to_date=\"20250731\"\n)\n\n# Fetch actual content of a snapshot\ncontent = collector.collect_snapshot_content(\n    \"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\",\n    \"20250713203024\"  # YYYYMMDDHHMMSS format\n)\n```\n\n## Verification\n\nVerification is separated from data collection. Use `ConsistencyVerifier` to validate evidence against original sources.\n\n```python\nfrom src.verifiers import ConsistencyVerifier\n\nverifier = ConsistencyVerifier()\n\n# Verify single evidence\nresult = verifier.verify(commit)\nif not result.is_valid:\n    print(f\"Errors: {result.errors}\")\n\n# Verify multiple\nresult = verifier.verify_all([commit, pr, issue])\n```\n\nOr use the convenience method on `EvidenceStore`:\n\n```python\nstore = EvidenceStore()\nstore.add_all([commit, pr, issue])\nis_valid, errors = store.verify_all()\n```\n\n## EvidenceStore\n\nStore, query, and export evidence collections.\n\n```python\nfrom src import EvidenceStore\nfrom datetime import datetime\n\nstore = EvidenceStore()\n\n# Add evidence\nstore.add(commit)\nstore.add_all([pr, issue, ioc])\n\n# Query\ncommits = store.filter(observation_type=\"commit\")\nrecent = store.filter(after=datetime(2025, 7, 1))\nfrom_github = store.filter(source=\"github\")\nfrom_git = store.filter(source=\"git\")\nrepo_events = store.filter(repo=\"aws\u002Faws-toolkit-vscode\")\n\n# Export\u002FImport\nstore.save(\"evidence.json\")\nstore = EvidenceStore.load(\"evidence.json\")\n\n# Summary\nprint(store.summary())\n# {'total': 5, 'events': {...}, 'observations': {...}, 'by_source': {...}}\n\n# Verify all against sources\nis_valid, errors = store.verify_all()\n```\n\n## Loading Evidence from JSON\n\n```python\nfrom src import load_evidence_from_json\nimport json\n\nwith open(\"evidence.json\") as f:\n    data = json.load(f)\n\nfor item in data:\n    evidence = load_evidence_from_json(item)\n    # Evidence is now a typed Pydantic model\n```\n\n## Evidence Types\n\n### Events (from GH Archive)\n\nAll 12 GitHub event types are supported:\n\n| Type | Description |\n|------|-------------|\n| PushEvent | Commits pushed |\n| PullRequestEvent | PR opened\u002Fclosed\u002Fmerged |\n| IssueEvent | Issue opened\u002Fclosed |\n| IssueCommentEvent | Comment on issue\u002FPR |\n| CreateEvent | Branch\u002Ftag created |\n| DeleteEvent | Branch\u002Ftag deleted |\n| ForkEvent | Repository forked |\n| WatchEvent | Repository starred |\n| MemberEvent | Collaborator added\u002Fremoved |\n| PublicEvent | Repository made public |\n| ReleaseEvent | Release published\u002Fcreated\u002Fdeleted |\n| WorkflowRunEvent | GitHub Actions run |\n\n### Observations (from GitHub API, Local Git, Wayback, Vendors)\n\n| Type | Description | Sources |\n|------|-------------|---------|\n| CommitObservation | Commit metadata and files | GitHub, Git, GH Archive |\n| IssueObservation | Issue or PR | GitHub, GH Archive |\n| FileObservation | File content at ref | GitHub |\n| BranchObservation | Branch HEAD | GitHub |\n| TagObservation | Tag target | GitHub |\n| ReleaseObservation | Release metadata | GitHub |\n| ForkObservation | Fork relationship | GitHub |\n| SnapshotObservation | Wayback snapshots | Wayback |\n| IOC | Indicator of Compromise | Vendor |\n| ArticleObservation | Security report\u002Fblog | Vendor |\n\n## IOC Types\n\n```python\nfrom src import EvidenceSource, IOCType\nfrom src.schema import IOC, VerificationInfo\nfrom pydantic import HttpUrl\nfrom datetime import datetime, timezone\n\n# IOCs are created directly as schema objects\nioc = IOC(\n    evidence_id=\"ioc-commit-sha-abc123\",\n    observed_when=datetime.now(timezone.utc),\n    observed_by=EvidenceSource.SECURITY_VENDOR,\n    observed_what=\"Malicious commit SHA found in vendor report\",\n    verification=VerificationInfo(\n        source=EvidenceSource.SECURITY_VENDOR,\n        url=HttpUrl(\"https:\u002F\u002Fvendor.com\u002Freport\")\n    ),\n    ioc_type=IOCType.COMMIT_SHA,\n    value=\"678851bbe9776228f55e0460e66a6167ac2a1685\",\n)\n```\n\nAvailable IOC types: `COMMIT_SHA`, `FILE_PATH`, `FILE_HASH`, `CODE_SNIPPET`, `EMAIL`, `USERNAME`, `REPOSITORY`, `TAG_NAME`, `BRANCH_NAME`, `WORKFLOW_NAME`, `IP_ADDRESS`, `DOMAIN`, `URL`, `API_KEY`, `SECRET`\n\n## Testing\n\n### Run Unit Tests\n\n```bash\ncd .claude\u002Fskills\u002Fgithub-forensics\u002Fgithub-evidence-kit\npip install -r requirements.txt\npytest tests\u002F -v --ignore=tests\u002Ftest_integration.py\n```\n\n### Run Integration Tests (Optional)\n\nIntegration tests hit real external services (GitHub API, BigQuery, vendor URLs):\n\n```bash\n# All integration tests\npytest tests\u002Ftest_integration.py -v -m integration\n\n# Skip integration tests in CI\npytest tests\u002F -v -m \"not integration\"\n```\n\n**Note**: GitHub API integration tests use 60 req\u002Fhr unauthenticated rate limit. BigQuery tests require credentials (see below).\n\n## GCP BigQuery Credentials (for GH Archive)\n\nGH Archive queries require Google Cloud BigQuery credentials. Two options:\n\n### Option 1: JSON File Path\n\n```bash\nexport GOOGLE_APPLICATION_CREDENTIALS=\u002Fpath\u002Fto\u002Fcredentials.json\n```\n\n### Option 2: JSON Content in Environment Variable\n\nUseful for `.env` files or CI secrets:\n\n```bash\nexport GOOGLE_APPLICATION_CREDENTIALS='{\"type\":\"service_account\",\"project_id\":\"...\",\"private_key\":\"...\"}'\n```\n\nThe client auto-detects JSON content vs file path.\n\n### Setup Steps\n\n1. Create a [Google Cloud Project](https:\u002F\u002Fconsole.cloud.google.com\u002F)\n2. Enable BigQuery API\n3. Create a Service Account with `BigQuery User` role\n4. Download JSON credentials\n5. Set `GOOGLE_APPLICATION_CREDENTIALS` env var\n\n**Free Tier**: 1 TB\u002Fmonth of BigQuery queries included.\n\n## Requirements\n\n```bash\npip install -r requirements.txt\n```\n\n- `pydantic` - Schema validation\n- `requests` - HTTP client\n- `google-cloud-bigquery` - GH Archive queries (optional)\n- `google-auth` - GCP authentication (optional)\n\n",{"name":5,"tags":49,"author":51,"version":52,"description":7},[26,50,38,25,39,40],"forensics","mbrg",2,"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fgadievron\u002Fraptor\u002Fgithub-evidence-kit",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":63,"prompt":73,"zipAvailable":74},[64,67,70],{"tool":65,"command":66},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill github-evidence-kit",{"tool":68,"command":69},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill github-evidence-kit",{"tool":71,"command":72},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill github-evidence-kit","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fgadievron\u002Fraptor\u002Fgithub-evidence-kit\u002FSKILL.md",true,[],[77,91,101,110,116,123],{"skillNo":78,"name":79,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":87,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[82],{"categoryNo":83,"categoryName":84,"taxonomyType":85,"taxonomyTypeDesc":86},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[88,89,90],"model","model hierarchy","model hierarchy skill",{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":97,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[96],{"categoryNo":83,"categoryName":84,"taxonomyType":85,"taxonomyTypeDesc":86},[98,99,100],"MCP","zoom","zoom mcp",{"skillNo":102,"name":103,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[107,108,109,99],"sdk","zoom apps sdk","apps",{"skillNo":111,"name":112,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":115,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[112],{"skillNo":117,"name":118,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":122,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[121],{"categoryNo":83,"categoryName":84,"taxonomyType":85,"taxonomyTypeDesc":86},[118],{"skillNo":124,"name":125,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[125]]