Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/agents/backend-reviewer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: backend-reviewer
description: Go backend review — correctness, concurrency safety, error handling, API contracts, reliability.
tools: [read, search]
---

You are a senior Go reviewer focused on correctness and reliability under load. For each issue cite `file:line` and propose the fix.

Check:

- **Error handling** — every error checked and wrapped with context (`fmt.Errorf("...: %w", err)`); none swallowed or logged-and-continued where it shouldn't be. No `panic` in library/request paths.
- **Concurrency** — data races (would it pass `go test -race`?), unguarded shared state, maps written concurrently, goroutines that can leak or block forever. Mutex scope correct.
- **Context** — `context.Context` plumbed through and its cancellation/deadline honoured on I/O and long operations.
- **Resources** — every `Open`/acquire has a matching `defer Close()`/release; no leaked connections, files, or rows.
- **API contracts** — request/response shapes, status codes, and pagination consistent; backward-compatible changes; input validated at the boundary.
- **Data layer** — queries parameterized; transactions scoped correctly; N+1 and obvious hot-path inefficiencies.
- **Tests** — table-driven where it fits; they exercise error and edge paths, not just the happy path.

Prefer fewer, high-confidence findings. Flag over-engineering and dead code. Leave security-specific deep-dives to `security-reviewer` but call out anything obviously unsafe.
19 changes: 19 additions & 0 deletions .github/agents/frontend-reviewer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: frontend-reviewer
description: TypeScript / Next.js review — server-client boundaries, XSS, accessibility, performance, brand consistency.
tools: [read, search]
---

You are a senior frontend reviewer for a Next.js (App Router) + TypeScript codebase. For each issue cite `file:line` and propose the fix.

Check:

- **Server/client boundaries** — `"use client"` only where needed; no server secrets imported into client components; data fetching on the server where it should be; hydration mismatches avoided.
- **XSS / injection** — no `dangerouslySetInnerHTML` without sanitization; URLs and user content escaped; no `eval`-like patterns.
- **Type safety** — no `any` smuggling past the type system; discriminated unions for state; exhaustive handling.
- **Accessibility** — semantic elements, labels on inputs, keyboard focus, alt text, color-contrast intent.
- **Performance** — unnecessary re-renders (stable keys, memo where it matters, no inline object/array props in hot lists); avoid large client bundles; image/font handling.
- **Brand/design consistency** — reuse the real design tokens and components (the V mark, brand colors `#1456F0`/`#EA5EC1`, Geist type). **Never invent a logo, color, or font** — flag any fabricated brand asset.
- **Tests** — components/logic covered; user-facing behavior asserted, not implementation details.

Prefer fewer, high-confidence findings. Flag dead code and over-abstraction.
20 changes: 20 additions & 0 deletions .github/agents/security-reviewer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: security-reviewer
description: Adversarial application-security review — OWASP, multi-tenant isolation, BYOK secrets, injection, crypto.
tools: [read, search]
---

You are a skeptical application-security reviewer. Your job is to find the vulnerability, not to be agreeable. Default to **"this is a finding"** when you are unsure, and say why. For every issue: cite `file:line`, name the vulnerability class **with its OWASP/CWE id**, describe the exploit, and propose the fix.

**Review against industry standards.** Map every finding to **OWASP Top 10 (2021)** and the **CWE Top 25** where it fits — e.g. A01 Broken Access Control (CWE-862/639), A02 Cryptographic Failures (CWE-327), A03 Injection (CWE-89/78/79), A04 Insecure Design, A05 Security Misconfiguration, A07 Identification & Auth Failures (CWE-287), A08 Software & Data Integrity (CWE-502 unsafe deserialization), A09 Logging Failures (e.g. secrets in logs), A10 SSRF (CWE-918). Naming the standard makes the finding actionable and auditable.

Hunt specifically for:

- **Broken authorization / multi-tenant data leakage** — any store, query, or API path that isn't scoped to the caller's org/tenant; cross-tenant read or write; missing ownership checks. This is the top risk in `vectorless-control-plane`. Trace the auth context from request to data access.
- **Secrets / BYOK handling** — model keys must be encrypted at rest (AES-256-GCM), never logged, never returned in API responses or error messages; no secrets in client bundles or committed files.
- **Injection** — SQL/command/template injection; always parameterize. **SSRF** on any URL/host taken from input. Unsafe deserialization.
- **Crypto** — weak algorithms, hardcoded keys/IVs, missing authentication on encryption, predictable randomness for security purposes.
- **AuthN** — token validation, session handling, missing rate limits on auth endpoints.
- **Dependencies** — newly added packages with known CVEs or low reputation (supply-chain risk).

Rank findings by severity (critical/high/medium/low). If you find nothing, say what you checked so the absence is meaningful. Do not comment on style or formatting — that is another reviewer's job.
17 changes: 17 additions & 0 deletions .github/agents/test-reliability-reviewer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: test-reliability-reviewer
description: Tests & reliability review — do the tests prove behavior, cover edges, and stay deterministic.
tools: [read, search]
---

You review whether a change is actually *proven* and *reliable* — not just whether it compiles. For each issue cite `file:line`.

Check:

- **Do the tests prove the behavior?** A test that passes without exercising the new logic is worthless. Would the test **fail** if the feature were broken? If not, say so.
- **Coverage gaps** — error paths, empty/nil/boundary inputs, concurrency, the specific scenario the issue describes. New behavior with no test is a finding.
- **Determinism / flakiness** — no reliance on wall-clock time, random without a seed, network, sleep-based timing, or ordering of maps/sets. Flag anything that could fail intermittently in CI.
- **Reliability of the change itself** — timeouts and retries on I/O, graceful degradation, idempotency where it matters, resource cleanup on the error path.
- **Test quality** — assertions on outcomes (not internals), clear arrange/act/assert, table-driven where it fits, no over-mocking that hides real behavior.

If the change has adequate tests, say what they cover so it's credible. Recommend the specific missing test cases by name.
22 changes: 22 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copilot review — baseline

You are reviewing a pull request for the Vectorless codebase. Review against the **issue's acceptance criteria** (linked via `Closes HAL-<n>`); flag scope creep. Be concrete: cite `file:line`, explain the risk, propose the fix. Prefer fewer, high-confidence findings over noise.

Review in this order, stop-and-flag if a level fails:

**1. Right thing** — Does the change do exactly what the issue asked, nothing more? Any unrelated edits, dead code, or commented-out blocks?

**2. Done right**
- Correctness & edge cases; nil/undefined and empty-input handling.
- Errors: wrapped with context, never swallowed; `context.Context` cancellation honoured (Go).
- Tests actually **prove** the new behavior (not just exist) and cover error/edge paths.
- Simplicity: is there a smaller solution? No premature abstraction.

**3. Safe (security-first)**
- **Authorization & multi-tenant isolation** — every store/query access scoped to the caller's tenant; no cross-tenant read/write. Highest priority in `vectorless-control-plane`.
- **Secrets / BYOK** — model keys encrypted at rest, never logged or echoed in responses.
- Injection (SQL/command), SSRF, unsafe deserialization, weak/missing crypto.
- New dependencies: justified, reputable, no known CVEs.
- Concurrency (Go): data races, unguarded shared state, leaked goroutines.

For deeper, area-specific review, the specialized agents in `.github/agents/` and the path-scoped rubrics in `.github/instructions/` apply automatically. When in doubt on a security question, **treat it as a finding** and say so explicitly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^|/)(copilot-instructions\.md|agents|instructions)' || true

echo
echo "== .github/copilot-instructions.md =="
if [ -f .github/copilot-instructions.md ]; then
  nl -ba .github/copilot-instructions.md | sed -n '1,120p'
fi

echo
echo "== .github/agents =="
if [ -d .github/agents ]; then
  find .github/agents -maxdepth 3 -type f -print | sort | while read -r f; do
    echo "--- $f"
    nl -ba "$f" | sed -n '1,160p'
  done
fi

echo
echo "== .github/instructions =="
if [ -d .github/instructions ]; then
  find .github/instructions -maxdepth 3 -type f -print | sort | while read -r f; do
    echo "--- $f"
    nl -ba "$f" | sed -n '1,160p'
  done
fi

Repository: hallelx2/pdftable

Length of output: 601


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .github/copilot-instructions.md =="
if [ -f .github/copilot-instructions.md ]; then
  awk '{printf "%6d  %s\n", NR, $0}' .github/copilot-instructions.md | sed -n '1,120p'
fi

echo
echo "== custom agent files =="
for f in .github/agents/*.agent.md; do
  [ -f "$f" ] || continue
  echo "--- $f"
  awk '{printf "%6d  %s\n", NR, $0}' "$f" | sed -n '1,180p'
done

echo
echo "== instruction files =="
for f in .github/instructions/*.instructions.md; do
  [ -f "$f" ] || continue
  echo "--- $f"
  awk '{printf "%6d  %s\n", NR, $0}' "$f" | sed -n '1,160p'
done

Repository: hallelx2/pdftable

Length of output: 11865


🌐 Web query:

GitHub Copilot custom agents applyTo path-specific instruction files automatic selection documentation

💡 Result:

In GitHub Copilot, path-specific instruction files are configured using *.instructions.md files, which allow you to define instructions that are applied automatically based on the files or directories currently being accessed [1][2][3]. Key details for implementation include: 1. Storage Location: These files should be stored within or below the .github/instructions directory in your repository [1][4][5]. 2. Configuration: Each .instructions.md file must include a YAML frontmatter block at the start of the file that defines the applyTo property [1][3]. This property uses glob syntax to determine which files the instructions apply to [1][2][3]. Example configuration: --- applyTo: "app/models//*.rb" --- 3. Automatic Selection: GitHub Copilot automatically selects and applies these instructions when the path of the file being worked on matches the glob pattern specified in the applyTo field [1][3]. If no applyTo property is defined, the instructions will not be applied automatically, though they may still be available for manual selection in some interfaces [3]. 4. Multiple Patterns: You can specify multiple patterns within the applyTo field by separating them with commas (e.g., applyTo: "/*.ts,/*.tsx") [1][2]. 5. Scope and Precedence: When a path matches, these path-specific instructions are used alongside repository-wide custom instructions (defined in .github/copilot-instructions.md) if they exist [1][5]. You can verify which instructions were applied by checking the References section of a Copilot chat response [3]. This functionality is supported in various Copilot features, including Copilot Chat in IDEs like Visual Studio Code and Visual Studio, as well as the Copilot cloud agent [4][6]. While custom agents (defined in files like AGENTS.md) and path-specific instructions both serve to customize behavior, they are distinct mechanisms; custom agents define broader agent profiles, whereas *.instructions.md files provide targeted, file-context-aware instructions [4][5][7].

Citations:


🌐 Web query:

GitHub Copilot custom agents *.agent.md automatic selection agents panel profile selection applyTo instructions

💡 Result:

GitHub Copilot custom agents are defined using Markdown files with the .agent.md extension [1][2]. These files use YAML frontmatter to configure the agent's identity, behavioral instructions, and capabilities [3][4]. Automatic Selection and the Agents Panel GitHub Copilot can automatically select and use a custom agent based on the task context [5]. Key configuration properties in the .agent.md file control this behavior: - disable-model-invocation: If set to true, this prevents Copilot from automatically using the agent based on task context; the agent must then be selected manually [5]. - user-invocable: If set to false, the agent cannot be manually selected by a user and is restricted to programmatic access [5]. - infer (Retired): Previously used to control automatic selection; it is now recommended to use disable-model-invocation and user-invocable instead [5]. In IDEs and GitHub interfaces, users can typically select agents manually from an agents panel, dropdown, or tab when initiating a new session [6][7][8]. Instructions and applyTo While custom agents use .agent.md files for their core definition [1][4], separate instruction files often use the *.instructions.md format [9][10]. These instruction files utilize the applyTo property to manage scope [9][11]: - applyTo: This property accepts glob patterns to specify which files or directories the instructions apply to [9][11][10]. For example, applyTo: "/*.ts" would apply the instructions to all TypeScript files [11][10]. If this property is omitted, the instructions may not be applied automatically [9]. - Custom Agent Instructions: Within an .agent.md file, the behavioral instructions are defined in the Markdown content below the YAML frontmatter [4][12]. These instructions guide the agent's expertise, constraints, and behavior during its execution [4][2]. In summary, .agent.md files define the custom agent itself, while *.instructions.md files are often used for repository-wide or path-specific behavioral rules governed by the applyTo property [9][13][10].

Citations:


Do not claim that custom agents apply automatically.

Path-specific .github/instructions/ files apply automatically when applyTo matches. Custom agents in .github/agents/ require explicit selection or assignment; do not present them as already running.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...cific review, the specialized agents in .github/agents/ and the path-scoped rubrics in...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...agents/and the path-scoped rubrics in.github/instructions/` apply automatically. Whe...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/copilot-instructions.md at line 22, Update the guidance in the
specialized-review paragraph to state that path-scoped files in
.github/instructions/ apply automatically only when their applyTo pattern
matches, while custom agents in .github/agents/ require explicit selection or
assignment. Remove the claim that specialized agents apply automatically, and
preserve the explicit security-finding guidance.

24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Dependency CVE automation. Dependabot opens PRs for vulnerable/outdated deps.
# Ecosystems with no manifest in a given repo are simply skipped.
# Also enable per repo: Settings → Code security → Dependabot alerts + security updates.
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
labels: [dependencies, security]
Comment on lines +6 to +10

- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
labels: [dependencies, security]
Comment on lines +12 to +17

- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
labels: [dependencies, security]
Comment on lines +19 to +24
Comment on lines +5 to +24

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Tracked files relevant to Dependabot/workflows:\n'
git ls-files | rg '(^|/)\.github/(dependabot\.yml|workflows/|pyproject\.toml|requirements|setup\.py|poetry\.lock|Pipfile\.lock)' || true

printf '\nCurrent .github/dependabot.yml:\n'
cat -n .github/dependabot.yml

printf '\nSearch for python dependency scanning declarations:\n'
rg -n "python|pip|safety|bandit|security|oss-supplier|dependency|dependabot|package-ecosystem" .github -S || true

printf '\nSearch for pip ecosystems in dependabot files:\n'
rg -n "package-ecosystem:\s*(pip|poetry|requirements)" .github || true

Repository: hallelx2/pdftable

Length of output: 7039


🌐 Web query:

GitHub Dependabot package-ecosystem pip depends on requirements.txt setup.py pyproject.toml

💡 Result:

To configure Dependabot to monitor your Python dependency files, use the pip package ecosystem in your .github/dependabot.yml file [1][2][3]. Dependabot supports requirements.txt, setup.py, and pyproject.toml files under this single ecosystem [4][5][6]. Configuration Details: - Ecosystem Name: Use package-ecosystem: "pip" [1][2][6]. - File Support: Dependabot monitors requirements.txt (any .txt file), setup.py, and pyproject.toml (if it follows PEP 621) when configured with the pip ecosystem [5][6]. It also supports related files like setup.cfg [5]. - Directory Configuration: Specify the directory where these files are located (e.g., directory: "/") [3]. To ensure Dependabot scans nested directories, you can use patterns like directory: "//*" [7]. Common Setup: A standard dependabot.yml configuration for a Python project typically looks like this [3]: version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" Important Considerations: - Grouped Updates: If you have multiple dependency files (e.g., both a pyproject.toml and a requirements.txt) and want them updated together, you may need to use Dependabot's grouping feature to prevent separate, uncoordinated pull requests [7][4]. - Limitations: Dependabot's ability to keep requirements.txt files synchronized with pyproject.toml changes—especially if the requirements file is generated by an external tool like pip-compile—can vary [8][9]. In some cases, Dependabot may update the pyproject.toml but not the associated requirements.txt if the relationship between the two is not natively recognized by its update logic [9]. If you rely on external tools to sync these files, you may need to manage those updates outside of standard Dependabot version updates or ensure the files are in locations Dependabot consistently crawls [7][9].

Citations:


🌐 Web query:

site:docs.github.com/dependabot/generate-dependabot.yml gomod npm pip

💡 Result:

Use these package-ecosystem values in .github/dependabot.yml:

version: 2
updates:
  - package-ecosystem: "gomod"
    directory: "/"
    schedule:
      interval: "weekly"

  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"

  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"

gomod is for Go modules; npm covers npm, Yarn, and pnpm; pip also covers pipenv and Poetry projects. [1][2]


Add pip updates to Dependabot.

Dependabot supports package-ecosystem: pip for Python requirement files, and target repositories synced to this config will not get Python update PRs without it. Add the same format as the existing npm/gomod update entries, with dependency manifest support matching the project.

🧰 Tools
🪛 GitHub Check: Semgrep OSS

[warning] 19-24: Semgrep Finding: package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown
This Dependabot configuration does not set a cooldown period. Newly published packages can be malicious or unstable. Add a cooldown block with default-days: 7 to each package-ecosystem entry under updates to wait 7 days before proposing updates to newly published package versions. Reference: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#cooldown


[warning] 12-17: Semgrep Finding: package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown
This Dependabot configuration does not set a cooldown period. Newly published packages can be malicious or unstable. Add a cooldown block with default-days: 7 to each package-ecosystem entry under updates to wait 7 days before proposing updates to newly published package versions. Reference: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#cooldown


[warning] 6-10: Semgrep Finding: package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown
This Dependabot configuration does not set a cooldown period. Newly published packages can be malicious or unstable. Add a cooldown block with default-days: 7 to each package-ecosystem entry under updates to wait 7 days before proposing updates to newly published package versions. Reference: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#cooldown

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/dependabot.yml around lines 5 - 24, Add a Dependabot update entry
for the pip package ecosystem alongside the existing npm and gomod entries,
targeting the repository root and using the same weekly schedule, pull-request
limit, and dependency/security labels. Configure its directory to match the
project’s Python dependency manifest location.

12 changes: 12 additions & 0 deletions .github/instructions/backend.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
applyTo: "**/*.go"
---

Go backend review for this file. Cite `file:line` + the fix.

- Errors checked and wrapped with context (`%w`); none swallowed; no `panic` in library/request paths.
- Concurrency: no data races (must pass `go test -race`), shared state guarded, no leaked/blocked goroutines.
- `context.Context` plumbed through; cancellation/deadlines honoured on I/O.
- Resources: every acquire has a matching `defer` release; no leaked connections/rows/files.
- Queries parameterized; input validated at the boundary; transactions scoped correctly.
- Tests exercise error and edge paths, not just the happy path. Flag dead code and over-engineering.
12 changes: 12 additions & 0 deletions .github/instructions/frontend.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
applyTo: "**/*.ts,**/*.tsx,**/*.css"
---

TypeScript / Next.js review for this file. Cite `file:line` + the fix.

- Server/client boundaries correct; no server secrets in client components; no hydration mismatches.
- No `dangerouslySetInnerHTML` without sanitization; user content/URLs escaped.
- No `any` smuggled past the types; exhaustive handling of unions.
- Accessibility: semantic elements, input labels, keyboard focus, alt text.
- Performance: avoid needless re-renders (stable keys, no inline object props in hot lists); watch bundle size.
- Brand consistency: reuse real design tokens/components (V mark, `#1456F0`/`#EA5EC1`, Geist). Never invent a logo/color/font.
11 changes: 11 additions & 0 deletions .github/instructions/security.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
applyTo: "**"
---

Security review for every changed file, against **OWASP Top 10 (2021)** + **CWE Top 25**. Treat an uncertain security question as a finding and say so. Cite `file:line`, the **OWASP/CWE id**, and the fix.

- **Authorization & multi-tenant isolation** — is every data access scoped to the caller's org/tenant? Any cross-tenant read/write, missing ownership check, or auth context that isn't threaded to the query? (Top risk in `vectorless-control-plane`.)
- **Secrets / BYOK** — model keys encrypted at rest, never logged, never returned in responses/errors; no secrets in client bundles or committed files.
- **Injection / SSRF** — parameterize queries; validate and allowlist any URL/host from input; no unsafe deserialization.
- **Crypto** — strong algorithms, no hardcoded keys/IVs, authenticated encryption, secure randomness.
- **Dependencies** — new packages justified, reputable, no known CVEs.
40 changes: 40 additions & 0 deletions .github/workflows/jules-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: jules-review

# Optional: auto-invoke Jules for a security-focused review on every PR.
# PRIMARY path is simply commenting "@jules review this PR for security" on a PR —
# Jules reads AGENTS.md + .github/agents/security-reviewer.agent.md and responds.
# This workflow automates that, but only runs when a JULES_API_KEY secret is present,
# so it no-ops safely in repos that haven't set one.

on:
pull_request:
types: [opened, synchronize, ready_for_review]

permissions:
contents: read
pull-requests: write

jobs:
jules:
runs-on: ubuntu-latest
steps:
- name: Guard — only run when a Jules key is configured
id: guard
run: |
if [ -n "${{ secrets.JULES_API_KEY }}" ]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
else
echo "enabled=false" >> "$GITHUB_OUTPUT"
echo "No JULES_API_KEY set — skipping automated Jules review. Use @jules on the PR instead."
fi
- name: Jules security review
if: steps.guard.outputs.enabled == 'true'
uses: sanjay3290/jules-pr-reviewer@f364d6653b2e9dc5a24df3ef12974aa264148c98 # v1.0.1
with:
jules-api-key: ${{ secrets.JULES_API_KEY }}
github-token: ${{ github.token }}
Comment on lines +30 to +35
review-prompt: >
Review this pull request as an adversarial application-security reviewer.
Follow .github/agents/security-reviewer.agent.md: hunt for broken authorization
and multi-tenant data leakage, BYOK secret handling, injection/SSRF, and weak
crypto. Default to "this is a finding" when unsure. Cite file:line and propose the fix.
139 changes: 139 additions & 0 deletions .github/workflows/security.reusable.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
name: security (reusable)

# Deterministic security scanners, written once and called by every repo via
# `.github/workflows/security.yml`. The AI reviewers (Copilot agents + Jules) sit
# on top of this. This layer catches the textbook vuln classes + real CVEs.
# Layers: secrets, dependency CVEs (multi-ecosystem + Go-specific), SAST against
# OWASP Top 10 / CWE Top 25, and infra/misconfig.

on:
workflow_call: {}

permissions:
contents: read
pull-requests: read
security-events: write

jobs:
secret-scan:
name: Secrets (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ github.token }}

sast-semgrep:
name: SAST — OWASP Top 10 + CWE Top 25 (Semgrep)
runs-on: ubuntu-latest
container:
image: semgrep/semgrep

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Tracked workflow file location:"
git ls-files .github/workflows/security*

echo
echo "Relevant workflow content:"
if [ -f .github/workflows/security.reusable.yml ]; then
  nl -ba .github/workflows/security.reusable.yml | sed -n '1,120p'
fi

echo
echo "Search for Semgrep image references:"
rg -n "semgrep/semgrep|image: " .github/workflows/security.reusable.yml || true

Repository: hallelx2/pdftable

Length of output: 327


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Relevant workflow snippets:"
awk '{printf "%8d  %s\n", NR, $0}' .github/workflows/security.reusable.yml | sed -n '1,120p'

echo
echo "Semgrep image references in workflow:"
grep -n "semgrep/semgrep\|image:" .github/workflows/security.reusable.yml || true

echo
echo "Check whether image reference has a digest:"
python3 - <<'PY'
from pathlib import Path
for line in Path(".github/workflows/security.reusable.yml").read_text().splitlines():
    stripped = line.strip()
    if stripped.startswith("image:") or stripped.startswith("image= "):
        value = stripped.split("=", 1)[1] if "=" in stripped else stripped.split(None, 1)[1]
        print(value, "has_digest:", "@" in value.split()[0])
PY

Repository: hallelx2/pdftable

Length of output: 5446


Pin the Semgrep container image to its SHA256 digest.

semgrep/semgrep is mutable by tag. A SHA256 digest can identify the reviewed Semgrep release as fixed image content.

Proposed fix
-      image: semgrep/semgrep
+      image: semgrep/semgrep@sha256:<reviewed-image-digest>
🧰 Tools
🪛 zizmor (1.28.0)

[error] 33-33: unpinned image references (unpinned-images): container image is unpinned

(unpinned-images)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/security.reusable.yml at line 33, Update the Semgrep
container image reference in the workflow’s image configuration to use the
reviewed release’s immutable SHA256 digest instead of the mutable
semgrep/semgrep tag.

Source: Linters/SAST tools

steps:
- uses: actions/checkout@v4
- name: Semgrep scan (industry rulesets)
run: |
semgrep scan \
--config p/owasp-top-ten \
--config p/cwe-top-25 \
--config p/secrets \
--config p/javascript \
--config p/typescript \
--config p/python \
--config p/github-actions \
--sarif --output semgrep.sarif || true
- name: Upload Semgrep SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep.sarif
continue-on-error: true

go-cves:
name: Go CVEs (govulncheck)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Detect Go module
id: detect
run: |
if [ -f go.mod ]; then echo "is_go=true" >> "$GITHUB_OUTPUT"; else echo "is_go=false" >> "$GITHUB_OUTPUT"; fi
- uses: actions/setup-go@v5
if: steps.detect.outputs.is_go == 'true'
with:
go-version: stable
- name: govulncheck (only CVEs that reach real call paths)
if: steps.detect.outputs.is_go == 'true'
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./... || true

go-sast:
name: Go SAST (gosec)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Detect Go module
id: detect
run: |
if [ -f go.mod ]; then echo "is_go=true" >> "$GITHUB_OUTPUT"; else echo "is_go=false" >> "$GITHUB_OUTPUT"; fi
- name: gosec
if: steps.detect.outputs.is_go == 'true'
uses: securego/gosec@9e6a9843d7a4a6e3e9a8539b02612c8a4aa3f889 # v2.27.1
with:
Comment on lines +82 to +85
args: -no-fail -fmt text ./...

node-cves:
name: Node/TS deps (npm audit)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Detect Node project
id: detect
run: |
if [ -f package.json ]; then echo "is_node=true" >> "$GITHUB_OUTPUT"; else echo "is_node=false" >> "$GITHUB_OUTPUT"; fi
- uses: actions/setup-node@v4
if: steps.detect.outputs.is_node == 'true'
with:
node-version: '20'
- name: npm audit (high + critical)
if: steps.detect.outputs.is_node == 'true'
run: |
npm install --package-lock-only --ignore-scripts 2>/dev/null || true
npm audit --audit-level=high || true

python-sast:
name: Python deps + SAST (pip-audit + bandit)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Detect Python project
id: detect
run: |
if ls requirements*.txt pyproject.toml setup.py >/dev/null 2>&1; then echo "is_py=true" >> "$GITHUB_OUTPUT"; else echo "is_py=false" >> "$GITHUB_OUTPUT"; fi
- uses: actions/setup-python@v5
if: steps.detect.outputs.is_py == 'true'
with:
python-version: '3.x'
- name: pip-audit (CVEs) + bandit (SAST)
if: steps.detect.outputs.is_py == 'true'
run: |
pip install --quiet pip-audit bandit
pip-audit || true
bandit -r . -ll || true
Comment on lines +112 to +125

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- workflow excerpt ---\n'
sed -n '90,140p' .github/workflows/security.reusable.yml 2>/dev/null || true

printf '\n--- pip-auss usages ---\n'
rg -n "pip-audit|projects_file|requirement|dependencies_file|bandit" .github/workflows || true

printf '\n--- repository manifest files ---\n'
git ls-files | rg '(^|/)(requirements[^[:space:]]*\.txt|pyproject\.toml|setup\.py|setup\.cfg|Pipfile|poetry\.lock|uv\.lock|Pipfile\.lock)$' || true

Repository: hallelx2/pdftable

Length of output: 246


🌐 Web query:

pip-audit command line documentation pip-audit . local project pyproject.toml requirements.txt default behavior no arguments

💡 Result:

The pip-audit tool is a vulnerability scanner for Python projects that audits dependencies against known vulnerabilities [1][2]. Its behavior depends on the arguments provided or the presence of a specific project path [3][4]. Default Behavior (No Arguments) When run without any arguments (pip-audit), the tool defaults to auditing the current active Python environment [3][5]. It inspects the installed packages in the environment and checks them against vulnerability databases [2]. Auditing Requirements Files To audit specific dependency files, use the -r or --requirement flag [3][4]. This flag can be used multiple times to audit multiple files (e.g., pip-audit -r requirements.txt -r dev-requirements.txt) [3][4]. pip-audit supports scanning requirements.txt files [4][2]. Auditing Local Projects You can audit a local project by providing its path as a positional argument [3]. When a project path is provided, pip-audit searches for specific "project" files, such as pyproject.toml [4]. Key Flags and Options -l, --local: Limits the audit to dependencies installed in the local environment, excluding globally installed packages if applicable [3][4]. --locked: Used when auditing from a project path to specifically audit lock files (currently supporting formats like pylock.*.toml) [3][4]. -f FORMAT, --format FORMAT: Specifies the output format (e.g., columns, json, cyclonedx-json, cyclonedx-xml, markdown) [6][3]. -s SERVICE, --vulnerability-service SERVICE: Selects the vulnerability service to use (options include osv, pypi, esms) [6][3]. -S, --strict: Causes the audit to fail if dependency collection fails for any dependency [6][3]. For detailed usage information, you can run pip-audit --help in your terminal [3][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workflow excerpt ---'
sed -n '90,145p' .github/workflows/security.reusable.yml

printf '%s\n' ''
printf '%s\n' '--- pip-audit/bandit usages ---'
rg -n "pip-audit|requirement|dependencies_file|bandit" .github/workflows || true

printf '%s\n' ''
printf '%s\n' '--- repository manifest files ---'
git ls-files | rg '(^|/)(requirements[^[:space:]]*\.txt|pyproject\.toml|setup\.py|setup\.cfg|Pipfile|poetry\.lock|uv\.lock|Pipfile\.lock)$' || true

Repository: hallelx2/pdftable

Length of output: 3007


Audit the repository dependency manifests.

pip-audit without an argument scans the current Python environment. This job only installs the audit tools, so repository dependencies are not scanned. Use pip-audit . for supported pyproject.toml projects and pip-audit -r "$requirements_file" for each requirements file. Keep Bandit under the existing Python-project detection condition.

🧰 Tools
🪛 GitHub Check: Semgrep OSS

[warning] 116-116: Semgrep Finding: yaml.github-actions.security.github-actions-mutable-action-tag.github-actions-mutable-action-tag
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/security.reusable.yml around lines 112 - 125, Update the
pip-audit step in the Python-project path to audit repository manifests rather
than only the current environment: run pip-audit . when pyproject.toml is
present, and run pip-audit -r "$requirements_file" for each matching
requirements file. Preserve the existing Python-project detection condition and
keep Bandit under that condition.


infra-trivy:
name: Vulns + misconfig (Trivy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Trivy (latest binary — avoids the action's broken setup-trivy pin)
run: curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
- name: Trivy filesystem scan
run: trivy fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL --ignore-unfixed --exit-code 0 --no-progress .

# Deepest free SAST = CodeQL. It needs per-repo language detection, so enable it
# per PUBLIC repo via Settings → Code security → Code scanning → Default setup (auto).
# Private repos (control-plane, deploy) rely on the Semgrep + OSV + gosec jobs above.
22 changes: 22 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: security

# Caller workflow. This exact file is SYNCED into every target repo by dev-standards,
# so each repo runs the same security scanners on every PR with zero per-repo config.
# It also runs here, scanning dev-standards itself.

on:
pull_request:
push:
branches: [main]

permissions:
contents: read
pull-requests: read
security-events: write

Comment on lines +12 to +16
jobs:
security:
# Local reference — the reusable file is synced into THIS repo too, so each repo
# is self-contained and this works whether dev-standards is public or private.
uses: ./.github/workflows/security.reusable.yml
secrets: inherit
Comment on lines +21 to +22
Loading
Loading