Skip to content

Commit f2cefcb

Browse files
committed
Add GitHub Actions security scanning workflows
- Secret scanning with detect-secrets (baseline mode) - Prompt injection detection with baseline support - Auto-fixes: trailing whitespace, EOF newlines - Updated baselines with legitimate test patterns - Scans on push/PR to main, master, develop branches Security scanning includes: - 20+ secret types (API keys, tokens, credentials) - 70+ prompt injection patterns (including Unicode steganography) - PTAB-specific attack vectors (trial data extraction, API bypass) - Git history scanning (last 100 commits)
1 parent 37e1a8c commit f2cefcb

File tree

8 files changed

+148
-21
lines changed

8 files changed

+148
-21
lines changed

.github/workflows/secret-scan.yaml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: Secret Scanning
2+
3+
on:
4+
push:
5+
branches: [ main, master, develop ]
6+
pull_request:
7+
branches: [ main, master, develop ]
8+
9+
jobs:
10+
secret-scan:
11+
name: Detect Secrets
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0 # Full history for comprehensive scanning
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: '3.11'
24+
25+
- name: Install detect-secrets
26+
run: |
27+
pip install detect-secrets
28+
29+
- name: Run detect-secrets scan
30+
run: |
31+
detect-secrets scan \
32+
--exclude-files 'configs/.*\.json' \
33+
--exclude-files '\.md$' \
34+
--exclude-files 'package-lock\.json' \
35+
--exclude-files '\.lock$' \
36+
--baseline .secrets.baseline
37+
38+
- name: Check for secrets in git history (last 100 commits)
39+
run: |
40+
# Scan recent git history for accidentally committed secrets
41+
git log --all --pretty=format: -p -100 | \
42+
detect-secrets scan --stdin \
43+
--exclude-files 'configs/.*\.json' \
44+
--exclude-files '\.md$' || true
45+
46+
- name: Security scan summary
47+
if: always()
48+
run: |
49+
echo "✅ Secret scanning complete"
50+
echo "If secrets were detected, the job will fail above"
51+
echo "To update baseline: detect-secrets scan --baseline .secrets.baseline"
52+
53+
prompt-injection-check:
54+
name: Prompt Injection Security Scan
55+
runs-on: ubuntu-latest
56+
57+
steps:
58+
- name: Checkout repository
59+
uses: actions/checkout@v4
60+
61+
- name: Set up Python
62+
uses: actions/setup-python@v5
63+
with:
64+
python-version: '3.11'
65+
66+
- name: Install uv
67+
uses: astral-sh/setup-uv@v3
68+
69+
- name: Install dependencies
70+
run: uv sync
71+
72+
- name: Run prompt injection detection (baseline mode)
73+
run: |
74+
echo "Scanning for NEW prompt injection patterns (baseline mode)..."
75+
76+
# Run our custom prompt injection scanner with baseline
77+
if uv run python .security/check_prompt_injections.py --baseline src/ tests/ *.md *.yml *.yaml *.json; then
78+
echo "✅ No NEW prompt injection patterns detected"
79+
echo " (Known findings are tracked in .prompt_injections.baseline)"
80+
else
81+
echo "❌ NEW prompt injection patterns found!"
82+
echo ""
83+
echo "These patterns may indicate attempts to:"
84+
echo "- Override system instructions (ignore previous instructions)"
85+
echo "- Extract sensitive prompts (show me your instructions)"
86+
echo "- Change AI behavior (you are now a different AI)"
87+
echo "- Manipulate PTAB data (extract all IPR trial numbers)"
88+
echo "- Bypass USPTO API restrictions (bypass PTAB API limits)"
89+
echo "- Hide malicious content (Unicode steganography)"
90+
echo ""
91+
echo "Please review the flagged content to ensure it is not malicious."
92+
echo ""
93+
echo "If these are legitimate patterns (test cases, documentation):"
94+
echo " 1. Verify they are not malicious"
95+
echo " 2. Run: uv run python .security/check_prompt_injections.py --update-baseline src/ tests/ *.md"
96+
echo " 3. Commit the updated .prompt_injections.baseline file"
97+
exit 1
98+
fi

.prompt_injections.baseline

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{}
1+
{}

.secrets.baseline

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@
9090
{
9191
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
9292
},
93+
{
94+
"path": "detect_secrets.filters.common.is_baseline_file",
95+
"filename": ".secrets.baseline"
96+
},
9397
{
9498
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
9599
"min_level": 2
@@ -129,6 +133,33 @@
129133
}
130134
],
131135
"results": {
136+
"deploy\\Validation-Helpers.psm1": [
137+
{
138+
"type": "Base64 High Entropy String",
139+
"filename": "deploy\\Validation-Helpers.psm1",
140+
"hashed_secret": "b173ce3ab26e49197a0a2c968ae03937ead2c080",
141+
"is_verified": false,
142+
"line_number": 129
143+
}
144+
],
145+
"scripts\\debug\\README.md": [
146+
{
147+
"type": "Secret Keyword",
148+
"filename": "scripts\\debug\\README.md",
149+
"hashed_secret": "a3e14ca24483c78554c083bc907c7194c7846ef1",
150+
"is_verified": false,
151+
"line_number": 54
152+
}
153+
],
154+
"scripts\\debug\\test_server.py": [
155+
{
156+
"type": "Secret Keyword",
157+
"filename": "scripts\\debug\\test_server.py",
158+
"hashed_secret": "b9615cef6cff3572af1365ff44c8b92ea9266f3e",
159+
"is_verified": false,
160+
"line_number": 21
161+
}
162+
],
132163
"tests\\test_deployment.py": [
133164
{
134165
"type": "Base64 High Entropy String",
@@ -155,5 +186,5 @@
155186
}
156187
]
157188
},
158-
"generated_at": "2026-01-19T04:59:40Z"
189+
"generated_at": "2026-01-19T06:52:23Z"
159190
}

.security/check_prompt_injections.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,4 @@ def main():
345345

346346

347347
if __name__ == '__main__':
348-
sys.exit(main())
348+
sys.exit(main())

INSTALL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ For workflow automation with **locally hosted n8n instances**, you can integrate
609609

610610
```bash
611611
npm install -g n8n
612-
612+
613613
# Or using Docker with required environment variable
614614
docker run -it --rm --name n8n -p 5678:5678 \
615615
-e N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true \
@@ -624,10 +624,10 @@ For workflow automation with **locally hosted n8n instances**, you can integrate
624624
# Method 1: Via n8n UI
625625
# Go to Settings > Community Nodes > Install
626626
# Enter: n8n-nodes-mcp
627-
627+
628628
# Method 2: Via npm (for self-hosted)
629629
npm install n8n-nodes-mcp
630-
630+
631631
# Method 3: Via Docker environment
632632
# Add to docker-compose.yml:
633633
# environment:
@@ -694,7 +694,7 @@ For workflow automation with **locally hosted n8n instances**, you can integrate
694694

695695
![n8n Execute Tool Operation](documentation_photos/n8n_PTAB_3.jpg)
696696

697-
-
697+
-
698698

699699
- Use "List Tools" operation to see available USPTO PTAB functions
700700
- Use "Execute Tool" operation with `search_trials_minimal`

reference/PTAB-to-ODP-PTAB-API-Mapping.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,4 +268,4 @@ GET /api/v1/patent/trials/decisions/search
268268
GET /api/v1/patent/appeals/decisions/search
269269
GET /api/v1/patent/ interferences/decisions/search
270270

271-
/decisions
271+
/decisions

reference/PTAB_swagger.yaml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,21 @@ components:
103103
$ref: ./odp-common-base.yaml#/components/schemas/PatentSearchRequest
104104
PatentDownloadRequest:
105105
$ref: ./odp-common-base.yaml#/components/schemas/PatentDownloadRequest
106-
PatentDataResponse:
106+
PatentDataResponse:
107107
$ref: ./odp-common-base.yaml#/components/schemas/PatentDataResponse
108-
ApplicationMetaData:
108+
ApplicationMetaData:
109109
$ref: ./odp-common-base.yaml#/components/schemas/ApplicationMetaData
110-
PatentTermAdjustment:
110+
PatentTermAdjustment:
111111
$ref: ./odp-common-base.yaml#/components/schemas/PatentTermAdjustment
112112
Assignment:
113113
$ref: ./odp-common-base.yaml#/components/schemas/Assignment
114-
RecordAttorney:
114+
RecordAttorney:
115115
$ref: ./odp-common-base.yaml#/components/schemas/RecordAttorney
116-
ParentContinuityData:
116+
ParentContinuityData:
117117
$ref: ./odp-common-base.yaml#/components/schemas/ParentContinuityData
118-
ChildContinuityData:
118+
ChildContinuityData:
119119
$ref: ./odp-common-base.yaml#/components/schemas/ChildContinuityData
120-
ForeignPriority:
120+
ForeignPriority:
121121
$ref: ./odp-common-base.yaml#/components/schemas/ForeignPriority
122122
EventData:
123123
$ref: ./odp-common-base.yaml#/components/schemas/EventData
@@ -128,7 +128,7 @@ components:
128128
GrantFileMetaData:
129129
$ref: ./odp-common-base.yaml#/components/schemas/GrantFileMetaData
130130
StatusCodeSearchResponse:
131-
$ref: ./odp-common-base.yaml#/components/schemas/StatusCodeSearchResponse
131+
$ref: ./odp-common-base.yaml#/components/schemas/StatusCodeSearchResponse
132132
# BulkData
133133
BdssResponseProductBag:
134134
$ref: ./odp-common-base.yaml#/components/schemas/BdssResponseProductBag
@@ -138,7 +138,7 @@ components:
138138
$ref: ./odp-common-base.yaml#/components/schemas/PetitionDecisionResponseBag
139139
PetitionDecisionIdentifierResponseBag:
140140
$ref: ./odp-common-base.yaml#/components/schemas/PetitionDecisionIdentifierResponseBag
141-
141+
142142
# Trial – Proceedings
143143
ProceedingDataResponse:
144144
$ref: ./trial-proceedings.yaml#/components/schemas/ProceedingDataResponse
@@ -203,5 +203,3 @@ components:
203203
$ref: ./trial-common.yaml#/components/schemas/Status413
204204
InternalError:
205205
$ref: ./trial-common.yaml#/components/schemas/InternalError
206-
207-

tests/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,10 @@ Tests run automatically on:
331331
# ✅ Good
332332
def test_trial_number_validation_accepts_valid_format():
333333
pass
334-
334+
335335
def test_trial_number_validation_rejects_invalid_format():
336336
pass
337-
337+
338338
# ❌ Bad
339339
def test_trial_number_validation():
340340
# Tests too many things

0 commit comments

Comments
 (0)