Back to skill

Security audit

sg-property-scraper

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Singapore property scraper with expected network use and optional commute lookup, but users should be mindful of third-party address sharing and unpinned dependencies.

Install in a virtual environment, avoid running pip as an administrator, and consider pinning dependency versions. Use --commute-to only when you are comfortable sending the destination address and scraped property addresses to Google Routes API. Avoid --no-validate and --raw-param unless you are intentionally testing unsupported PropertyGuru query parameters.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:23
Finding
Unpinned Third-Party Dependencies in Skill Installation Instructions## Vulnerability Details **File Location**: `SKILL.md:23-27` **Vulnerability Type**: Supply-chain exposure through unpinned dependencies **Risk Level**: Medium **Vulnerable Code Snippet**: ```markdown ## Dependencies - Python 3.8+ - `pip install curl_cffi beautifulsoup4 lxml` - Optional: `GOOGLE_MAPS_API_KEY` env var for commute time calculation (Google Routes API) ``` ### Technical Analysis The Skill directs users or automated agents to install `curl_cffi`, `beautifulsoup4`, and `lxml` without specifying reviewed versions, cryptographic hashes, a lockfile, or an explicit trusted package index. Package names are legitimate and no direct evidence indicates that they are currently malicious. However, unconstrained resolution allows installation behavior to change after the Skill has been audited. A future compromised release, package-index compromise, dependency compromise, or unexpected breaking release could introduce attacker-controlled code. Python package installation may execute build backend code for source distributions. Installed packages are also imported by `scripts/scrape.py`, allowing malicious module initialization code to execute when the scraper runs. ### Attack Path 1. A user or agent follows the dependency installation command in `SKILL.md`. 2. `pip` resolves the latest available versions and transitive dependencies from its configured package index. 3. An upstream package, transitive dependency, release artifact, or configured index is compromised. 4. Malicious code executes during source-package building or when the installed module is subsequently imported. 5. The code runs with the privileges of the account performing installation or running the Skill. ### Impact Assessment Successful exploitation could provide arbitrary code execution under the installing or executing user's account. The resulting access could include reading files and environment variables available to that account, mod ...[truncated 302 chars]
Remediation
## Remediation Suggestions 1. Provide a reviewed and version-pinned dependency file, for example: ```text curl_cffi==<reviewed-version> beautifulsoup4==<reviewed-version> lxml==<reviewed-version> ``` 2. Generate and verify SHA-256 hashes for every direct and transitive dependency, then install with: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Use a lockfile generated by a dependency-management tool so transitive versions are reproducible. 4. Specify a trusted package index explicitly and prevent unintended fallback to additional indexes. 5. Run dependency installation and the scraper in an isolated virtual environment or restricted container. 6. Add automated dependency vulnerability and provenance scanning to the release process. 7. Keep `SKILL.md` synchronized with the hardened installation procedure rather than retaining the unconstrained command.

T08 · Insecure Dependencies

Warning
Location
README.md:5
Finding
Unpinned Third-Party Dependencies in README Setup Command## Vulnerability Details **File Location**: `README.md:5-10` **Vulnerability Type**: Supply-chain exposure through unpinned dependencies **Risk Level**: Medium **Vulnerable Code Snippet**: ```markdown ## Setup ```bash # Python 3.8+ required pip install curl_cffi beautifulsoup4 lxml ``` ``` ### Technical Analysis The documented setup command resolves mutable package versions without a lockfile, exact version constraints, artifact hashes, or an explicitly trusted index. Consequently, two installations performed at different times can install different code even though the audited project files have not changed. The risk includes compromise of a direct dependency, compromise of a transitive dependency, malicious artifacts from an incorrectly configured package index, and execution of unreviewed build backend logic. The scraper later imports these dependencies, so malicious code can also execute at application startup. The command does not itself prove malicious intent, and the named dependencies are consistent with the declared scraping functionality. The issue is the absence of controls needed to make dependency installation reproducible and auditable. ### Attack Path 1. A user copies the setup command from `README.md`. 2. `pip` selects current package releases and their transitive dependencies. 3. A selected distribution or dependency has been compromised or replaced in the configured index. 4. Attacker-controlled code runs during package construction, installation, or a later import by `scripts/scrape.py`. 5. The attacker obtains code execution in the context used to install or run the project. ### Impact Assessment Exploitation could allow access to user-readable data, environment variables, project files, network connectivity, and credentials available to the process. It could also permit modification of files writable by the current account. The maximum privilege is normally that of the user executin ...[truncated 165 chars]
Remediation
## Remediation Suggestions 1. Replace the direct installation command with installation from a reviewed, version-pinned requirements file. 2. Pin all transitive dependencies and include cryptographic hashes for downloaded artifacts. 3. Use `python3 -m pip` from a dedicated virtual environment rather than an ambiguous global `pip` executable. 4. Document a trusted index URL and prohibit unreviewed extra indexes. 5. Add guidance not to run dependency installation as root or an administrator. 6. Periodically update pinned versions through a controlled process that includes vulnerability scanning and code review. 7. Ensure the README and `SKILL.md` reference the same locked dependency manifest.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (8)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
|------|-------------|
| `--pages N` | Number of pages to scrape (default: 1) |
| `--dry-run` | Build and print URL(s), skip scraping |
| `--no-validate` | Skip parameter validation |
| `--timeout N` | HTTP request timeout in seconds (default: 30) |
| `--raw-param K=V` | Extra URL query param (repeatable) |
| `--output json\|text\|none` | Output format (default: json when piped) |
Confidence
95% confidence
Finding
Exposing --no-validate and arbitrary --raw-param options creates a parameter-smuggling surface that can bypass intended input constraints and allow unreviewed query parameters to be sent upstream. In an agent context, this weakens guardrails, can trigger unexpected remote behavior, and may facilitate abuse of the target service or accidental leakage of sensitive values into requests.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
help="Number of pages to scrape (default: 1)")
    e.add_argument("--dry-run", action="store_true",
                   help="Build and print URL(s) only, skip scraping")
    e.add_argument("--no-validate", action="store_true",
                   help="Skip parameter validation")
    e.add_argument("--timeout", type=int, default=30,
                   help="HTTP request timeout in seconds (default: 30)")
Confidence
87% confidence
Finding
The --no-validate flag disables input validation, and the tool also supports raw query parameter injection via --raw-param. In an agent context, this increases the chance of policy bypass, unbounded or unsupported query construction, and misuse of the scraper against the upstream service because safety constraints can be intentionally disabled by callers.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill declares executable/network-capable behavior but does not constrain or document tool scope with explicit permissions or allowed-tools metadata. In an agent ecosystem, that increases the chance the skill is invoked with broader-than-necessary access to environment variables, local files, and outbound network requests, weakening least-privilege controls.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The description says to use the skill when asked to "search Singapore properties" or "find rental or sale listings," which are broad natural-language triggers without clear exclusion conditions. This may cause unintended invocation for general discussion or advice requests about Singapore property rather than explicit scraping/search tasks.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The markdown notes that commute time uses Google Routes API but does not clearly warn that user-supplied destination addresses are transmitted to a third party. This can lead to inadvertent disclosure of sensitive location information such as home, workplace, clinic, or school addresses without informed user consent.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
When commute calculation is enabled, the tool sends scraped property addresses together with a user-supplied destination to Google Routes API. That can disclose potentially sensitive user intent, destination information, and search context to a third party without any explicit notice, consent flow, or minimization controls; in an agent setting, users may not realize this data leaves the local tool boundary.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The Accept-Language header is fixed to en-US,en;q=0.9, which imposes a specific language/locale preference in network requests. The file does not offer a locale option or explain why this locale is required, so it constitutes a natural-language locale policy issue under the stated rule.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Content
"commute_to": "commuteTo",
    }
    for arg_name, param_name in cli_map.items():
        value = getattr(args, arg_name, None)
        if value is not None:
            params[param_name] = value
Confidence
50% confidence
Finding
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Static analysis

No suspicious patterns detected.