T01 · Skill Instruction Hijacking
- Location
SKILL.md:24- Finding
Mandatory Agent instruction override and persistent memory modification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real procurement-monitoring tool, but it needs review because it browses user-supplied sites with weak containment and auto-loads local JavaScript adapters with broad privileges.
Review before installing. Run this only in a contained environment or dedicated low-privilege account, avoid custom adapters unless you trust and review their code, do not enable webhooks for sensitive opportunities without accepting third-party data exposure, and prefer a version that restores Chromium sandboxing, validates destinations, pins setup commands, and constrains plugin loading.
SKILL.md:24Mandatory Agent instruction override and persistent memory modification
src/detail-fetcher.js:159Unrestricted browser navigation permits server-side request forgery
src/scanner.js:76Chromium sandbox is disabled while visiting untrusted websites
src/platforms/registry.js:36Custom adapters execute arbitrary JavaScript before validation
bin/bidding-hunter.js:287Adapter creation permits path traversal and generated JavaScript injection
package-lock.json:29Committed dependency lockfile uses a third-party package mirror
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Thumbs.db
# Environment
.env
.env.local
# Coverage
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Environment
.env
.env.local
# Coverage
coverage/
The document claims the tool is not a scraper for arbitrary websites, but later provides an arbitrary-URL exploration workflow and user-added adapters. This contradiction is dangerous because it normalizes broader capabilities than advertised and can bypass operator expectations or governance controls based on the declared scope.
Auto-discovering and loading JavaScript from built-in, user-home, and configurable custom paths creates an arbitrary code execution extension point. Any malicious or tampered adapter/notifier file in those locations would run with the privileges of the bidding-hunter process, enabling data exfiltration, filesystem access, or command execution.
The declared description presents a full procurement monitoring engine with automated scanning across multiple Chinese procurement platforms, configurable keyword matching, bid status tracking, deadline-aware reporting, and built-in adapters. The supplied code chunk does not implement those core behaviors. Instead, it is a developer/agent-oriented utility that prints step-by-step guidance for exploring a new platform and, optionally, uses Playwright to open one URL and collect structural hints such as likely procurement links, pagination presence, table/container patterns, and page title. This is related to the procurement-adapter ecosystem, but its primary purpose is adapter reconnaissance and scaffolding assistance, not procurement discovery or reporting. Because the code’s actual behavior is materially narrower and different from the declared primary purpose, this is a clear description-behavior mismatch.
The code is aligned with part of the declared purpose: it searches a Chinese procurement-related platform using configurable keywords and collects dated listings. However, the declared description presents a broader engine with multiple platform coverage, status tracking, and deadline-aware reporting. This specific code chunk only implements a single-platform scraper/adapter for Hebei search results and simple extraction of items. That makes the behavior materially narrower than the declared purpose. There is no evidence of unrelated or dangerous extra capabilities, but there is a description-behavior mismatch because important claimed capabilities are not represented in the supplied code chunk.
The code is broadly consistent with a procurement discovery/scanning component, but it does not fully match the declared description. It only covers one adapter ('national') for a single platform, not a multi-platform engine by itself. Its behavior is limited to scraping listings from six sub-sources within that platform, filtering by date, and optionally searching user queries for one source. There is no evidence in this chunk of bid status tracking, deadline-aware reporting, or a general plugin model. The mismatch is material because the declared purpose describes a broader system capability set than this code actually performs.
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
// === init ===
program.command('init')
.description('Create initial config file')
.option('-f, --force', 'Overwrite existing config')
.action(async (opts) => {
const configPath = path.resolve(
(program.opts().config || '~/.bidding-hunter/config.yaml').replace(/^~/, process.env.HOME || '/home/$USER')
The lockfile includes brace-expansion 1.1.16, which is flagged for denial-of-service conditions caused by unbounded expansion behavior. In this project it is only present as a transitive dev dependency under eslint/minimatch, so exploitation would mainly matter during developer-side tooling runs rather than the production bid-discovery workflow, but it is still a real supply-chain weakness if untrusted patterns are processed.
The lockfile includes fast-uri 3.1.4 via ajv, and the cited advisories describe URI parsing ambiguities that can lead to host confusion or SSRF in applications that make security decisions from parsed URLs. This package-lock.json alone does not prove the application parses attacker-controlled URLs for outbound requests, so the issue is context-dependent, but in a scraper with extensible plugins and configurable monitoring targets, malformed URL handling could become relevant and should be treated as a real risk.
The lockfile includes js-yaml 4.3.0, which is associated with CPU-exhaustion parsing issues. Given this skill explicitly uses YAML and allows user configuration, a maliciously crafted configuration file could plausibly trigger excessive CPU consumption and disrupt scans or automation, making this more relevant than a purely unused transitive dependency.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
The contribution instructions tell users to run npx playwright install chromium without pinning a specific Playwright version. Using npx this way can fetch and execute whatever package version is current at install time, which creates a supply-chain risk if a bad release, typo-squat, or compromised package is served. In a contributor setup document, this is more dangerous because readers are explicitly encouraged to execute the command locally.
Line L94 states 'Chinese comments for platform-specific logic,' which imposes a specific language requirement in project instructions. This is a natural-language locale policy issue because it forces one language without user opt-in or a documented regional/compliance justification.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
6. Ingest into database:
├── Skip existing URLs
├── Assign new aliases
└── Create history entries
7. Fetch details (for tracked entries without deadlines)
├── Parallel with concurrency limit
The extension guide explicitly introduces an exploration mode that accepts an arbitrary URL and has the agent identify selectors, pagination, and extraction logic. That expands the tool from a fixed procurement monitor into a general-purpose website exploration and scraping assistant, increasing abuse potential and weakening the stated scope boundary.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
The agent will navigate the site, identify listing pages, pagination, and extraction selectors.
2. **Create adapter from template**:
```bash
bidding-hunter create-adapter --name "my-platform"
The entire skill documentation is presented only in Chinese, including installation, usage, and safety information, with no indication that users may choose another language or that the tool is intentionally limited to a Chinese-speaking audience. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.
The README instructs users to run npx playwright install chromium, which can cause npx to fetch and execute an unpinned package version at install time. If the upstream package is compromised or a breaking release is published, users could execute unintended code on their machines during setup.
The skill describes networked scraping, browser automation, filesystem access, and use of environment-backed webhooks, but it does not declare an explicit permission or allowed-tools scope. That weakens containment and review because an agent may execute broader capabilities than users expect, especially when the document also contains strong tool-discipline instructions that normalize code and network use.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
### Rules (ZERO EXCEPTIONS)
1. **Use tools, don't replace them.** A bidding-hunter task is a tool-execution task, NOT a coding task.
2. **No ad-hoc scripts.** Do NOT write `scrape_*.js`, `fetch_*.js`, `test_*.js`, inline `node -e "..."`, `curl`, `web_fetch`, or any one-off scraping code.
3. **No browser shortcuts.** Do NOT use Playwright/Selenium directly unless you are inside a platform adapter's `scan()` method. All browser orchestration is handled by the scanner.
4. **No manual dedup/matching.** Do NOT copy-paste from the matcher or database modules. Use `bidding-hunter scan` → `bidding-hunter report`.
The document claims 'No privacy leakage' and 'all data stays local' while also supporting outbound Feishu and Slack webhooks. That contradiction can cause users to enable notifications without understanding that bid data, keywords, or metadata may be transmitted to third-party services, undermining informed consent and safe deployment decisions.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
This navigates to the site and captures structural hints.
2. **Create adapter template**:
```bash
bidding-hunter create-adapter --name new-site
The skill provides concrete webhook configuration examples but does not warn that scan results and related metadata may leave the local system. For procurement monitoring, this may expose commercially sensitive interests, internal keywords, or opportunity-tracking data to third-party messaging platforms and anyone with access to those channels.
The troubleshooting step uses npx playwright install chromium without pinning a version, which can pull whatever package version is current at execution time. This creates supply-chain and reproducibility risk: behavior can change unexpectedly, and a compromised or malicious upstream release would be executed in the user's environment.
No suspicious patterns detected.