From d5c90fc40661cf29634a25da560ad721b786643b Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 01:07:02 -0700 Subject: [PATCH 1/9] Added support for custom_rules and fixed the posting of the socket facts json file --- .gitignore | 4 +- Dockerfile | 9 +- README.md | 10 +- docs/github-action.md | 38 ++-- docs/local-install-docker.md | 70 +++--- docs/pre-commit-hook.md | 2 +- pyproject.toml | 5 +- socket_basics/connectors.yaml | 12 + socket_basics/core/config.py | 43 +++- .../core/connector/opengrep/__init__.py | 49 +++- .../core/connector/opengrep/custom_rules.py | 210 ++++++++++++++++++ .../core/connector/socket_tier1/scanner.py | 9 +- socket_basics/socket_basics.py | 22 +- socket_basics/version.py | 2 +- 14 files changed, 401 insertions(+), 84 deletions(-) create mode 100644 socket_basics/core/connector/opengrep/custom_rules.py diff --git a/.gitignore b/.gitignore index 8d193af..2272eac 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ file_generator.py *.md test_results local_tests/ +custom_rules/ # Common Python ignores __pycache__/ @@ -99,4 +100,5 @@ logs/ # Ignore output logs and generated src files *.log -.python-version \ No newline at end of file +.python-version +.socket.fact.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 203174d..13cd03f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,13 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Install system dependencies RUN apt-get update && apt-get install -y curl git wget +# Install Node.js 22.x +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get install -y nodejs + +# Install Socket CLI globally +RUN npm install -g socket + # Install Trivy RUN curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.67.2 @@ -30,7 +37,7 @@ COPY uv.lock /socket-basics/uv.lock # Install Python dependencies using uv from the project root WORKDIR /socket-basics RUN pip install -e . && uv sync --frozen --no-dev -ENV PATH="/socket-basics/.venv/bin:/root/.opengrep/cli/latest:$PATH" +ENV PATH="/socket-basics/.venv/bin:/root/.opengrep/cli/latest:/usr/bin:$PATH" # Use socket-basics as the default entrypoint ENTRYPOINT ["socket-basics"] diff --git a/README.md b/README.md index 22bb199..a6687a3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.11 + uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.11 . +docker build -t socketdev/socket-basics:1.0.12 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.11 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.12 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index 4c7292e..18fa0bb 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.11 + uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.11 +> - uses: SocketDev/socket-basics@1.0.12 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.11 +- uses: SocketDev/socket-basics@1.0.12 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.11 + uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.11 + uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.11:${{ github.sha }} . + run: docker build -t myapp:1.0.12:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.11 + uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.11 + uses: SocketDev/socket-basics@1.0.12 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.11 + - uses: SocketDev/socket-basics@1.0.12 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 03343c7..71bd0be 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.11 . +docker build -t socket-basics:1.0.12 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.11 . +docker build -t socket-basics:1.0.12 . # Or build with latest tag -docker build -t socket-basics:1.0.11:latest . +docker build -t socket-basics:1.0.12:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.11 . +docker build -t myorg/security-scanner:1.0.12 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.11 . +docker build --platform linux/amd64 -t socket-basics:1.0.12 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.11 socket-basics --version -docker run --rm socket-basics:1.0.11 socket --version -docker run --rm socket-basics:1.0.11 trivy --version -docker run --rm socket-basics:1.0.11 semgrep --version -docker run --rm socket-basics:1.0.11 trufflehog --version +docker run --rm socket-basics:1.0.12 socket-basics --version +docker run --rm socket-basics:1.0.12 socket --version +docker run --rm socket-basics:1.0.12 trivy --version +docker run --rm socket-basics:1.0.12 semgrep --version +docker run --rm socket-basics:1.0.12 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.11 + socket-basics:1.0.12 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.11').inside( + docker.image('socket-basics:1.0.12').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.11 + image: socket-basics:1.0.12 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.11 + socket-basics:1.0.12 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.11 + socket-basics:1.0.12 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.11 \ + socket-basics:1.0.12 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.11 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.12 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.11 .' +alias sb-build='docker build -t socket-basics:1.0.12 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.11" +IMAGE_NAME="socket-basics:1.0.12" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 836a82a..985cbb5 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.11 . +docker build -t socket-basics:1.0.12 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index f5f8a4e..ad1983e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.11" +version = "1.0.12" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" @@ -28,7 +28,8 @@ dependencies = [ "light-s3-client~=0.0.30", "PyYAML>=6.0.0", "tomli; python_version < '3.11'", - "socketdev>=0.1.0", + "socketdev>=3.0.14", + "jsonschema>=4.25.1" ] [project.optional-dependencies] diff --git a/socket_basics/connectors.yaml b/socket_basics/connectors.yaml index ae6f741..5dbe263 100644 --- a/socket_basics/connectors.yaml +++ b/socket_basics/connectors.yaml @@ -151,6 +151,18 @@ connectors: env_variable: INPUT_OPENGREP_NOTIFICATION_METHOD type: str default: "" + - name: use_custom_sast_rules + option: --use-custom-sast-rules + description: "Use custom SAST rules instead of bundled rules (falls back to bundled rules for languages without custom rules)" + env_variable: INPUT_USE_CUSTOM_SAST_RULES + type: bool + default: false + - name: custom_sast_rule_path + option: --custom-sast-rule-path + description: "Relative path to custom SAST rules directory (relative to workspace if set, otherwise cwd)" + env_variable: INPUT_CUSTOM_SAST_RULE_PATH + type: str + default: "custom_rules" # Python rule configuration - name: python_enabled_rules diff --git a/socket_basics/core/config.py b/socket_basics/core/config.py index acd6372..aacfd0f 100644 --- a/socket_basics/core/config.py +++ b/socket_basics/core/config.py @@ -10,7 +10,9 @@ import yaml import logging from pathlib import Path -from typing import Dict, Any, List +from typing import Dict, Any, List, Optional + +logger = logging.getLogger(__name__) class Config: @@ -284,6 +286,42 @@ def build_filtered_opengrep_rules(self) -> Dict[str, List[str]]: # Convert sets to lists for output return {k: list(v) for k, v in rule_file_filters.items()} + def get_custom_rules_path(self) -> Optional[Path]: + """Get the absolute path to custom SAST rules directory. + + Returns path relative to workspace if workspace is set, otherwise relative to cwd. + Returns None if custom rules are not enabled or path doesn't exist. + """ + if not self.get('use_custom_sast_rules', False): + return None + + custom_path_str = self.get('custom_sast_rule_path', 'custom_rules') + if not custom_path_str: + return None + + # Determine base path + try: + if hasattr(self, 'workspace') and self.workspace: + base_path = Path(self.workspace) + else: + base_path = Path.cwd() + except Exception: + base_path = Path.cwd() + + # Resolve custom rules path + custom_path = base_path / custom_path_str + + # Check if path exists + if not custom_path.exists(): + logger.warning(f"Custom SAST rules path does not exist: {custom_path}") + return None + + if not custom_path.is_dir(): + logger.warning(f"Custom SAST rules path is not a directory: {custom_path}") + return None + + return custom_path + # Centralized environment variable getters # All connectors and notifiers should use these methods instead of calling os.getenv directly @@ -1102,6 +1140,9 @@ def create_config_from_args(args) -> Config: # Override config with CLI args if args.workspace: config_dict['workspace'] = args.workspace + # When workspace is explicitly set, default output_dir to workspace unless OUTPUT_DIR env var is set + if 'OUTPUT_DIR' not in os.environ: + config_dict['output_dir'] = args.workspace if args.scan_files: config_dict['scan_files'] = args.scan_files # Console tabular flag (new) with fallback to deprecated name diff --git a/socket_basics/core/connector/opengrep/__init__.py b/socket_basics/core/connector/opengrep/__init__.py index f97db76..cb234b0 100644 --- a/socket_basics/core/connector/opengrep/__init__.py +++ b/socket_basics/core/connector/opengrep/__init__.py @@ -21,6 +21,7 @@ # Import individual notifier modules from . import github_pr, slack, ms_teams, ms_sentinel, sumologic, console, jira, webhook, json_notifier +from .custom_rules import CustomRulesBuilder # Import shared formatters from ...formatters import get_all_formatters @@ -46,7 +47,20 @@ def scan(self) -> Dict[str, Any]: targets = self.config.get_scan_targets() - # Locate rules directory + # Check if custom rules mode is enabled + custom_rules_path = self.config.get_custom_rules_path() + custom_rule_files: Dict[str, Path] = {} + + if custom_rules_path: + logger.info(f"Custom SAST rules enabled, loading from: {custom_rules_path}") + try: + builder = CustomRulesBuilder(custom_rules_path) + custom_rule_files = builder.build_rule_files(rule_files) + except Exception as e: + logger.error(f"Failed to build custom rule files: {e}", exc_info=True) + custom_rule_files = {} + + # Locate bundled rules directory for fallback module_dir = Path(__file__).resolve().parents[3] bundled_rules_dir = module_dir / 'rules' rules_dir = self.config.get('opengrep_rules_dir') or (str(bundled_rules_dir) if bundled_rules_dir.exists() else None) @@ -71,12 +85,22 @@ def scan(self) -> Dict[str, Any]: filtered = {} config_args: List[str] = [] + + # Build config_args using custom rules where available, falling back to bundled rules if filtered: + # When specific rules are enabled, use filtered approach for rf, enabled_ids in filtered.items(): - p = Path(rules_dir) / rf - if not p.exists(): - logger.debug('Rule file missing: %s', p) - continue + # Check if we have a custom rule file for this language + if custom_rule_files and rf in custom_rule_files: + p = custom_rule_files[rf] + logger.info(f"Using custom rules for {rf}") + else: + # Fall back to bundled rules + p = Path(rules_dir) / rf + if not p.exists(): + logger.debug('Rule file missing: %s', p) + continue + try: with open(p, 'r') as fh: data = yaml.safe_load(fh) or {} @@ -88,10 +112,21 @@ def scan(self) -> Dict[str, Any]: except Exception: logger.debug('Failed reading/parsing rule file %s', p, exc_info=True) else: + # No filtering - use entire rule files for rf in rule_files: - p = Path(rules_dir) / rf - if p.exists(): + # Check if we have a custom rule file for this language + if custom_rule_files and rf in custom_rule_files: + p = custom_rule_files[rf] + logger.info(f"Using custom rules for {rf}") config_args.extend(['--config', str(p)]) + else: + # Fall back to bundled rules + p = Path(rules_dir) / rf + if p.exists(): + logger.debug(f"Using bundled rules for {rf}") + config_args.extend(['--config', str(p)]) + else: + logger.warning(f"No rules found for {rf} (neither custom nor bundled)") # If nothing selected, only include all bundled rule files when the # caller explicitly requested all languages or all rules. Otherwise diff --git a/socket_basics/core/connector/opengrep/custom_rules.py b/socket_basics/core/connector/opengrep/custom_rules.py new file mode 100644 index 0000000..9a5ce71 --- /dev/null +++ b/socket_basics/core/connector/opengrep/custom_rules.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +""" +Custom SAST Rules Builder for OpenGrep + +Handles loading, parsing, and organizing custom SAST rules from a directory structure. +Groups rules by language and creates temporary rule files for OpenGrep execution. +""" + +import logging +import tempfile +import yaml +from pathlib import Path +from typing import Dict, Any, List, Optional + +logger = logging.getLogger(__name__) + + +class CustomRulesBuilder: + """Builds custom rule files from a custom rules directory.""" + + # Map of languages in rule `languages` field to Socket's rule file naming convention + LANGUAGE_TO_RULE_FILE = { + 'python': 'python.yml', + 'javascript': 'javascript_typescript.yml', + 'typescript': 'javascript_typescript.yml', + 'go': 'go.yml', + 'java': 'java.yml', + 'ruby': 'ruby.yml', + 'php': 'php.yml', + 'c': 'c_cpp.yml', + 'cpp': 'c_cpp.yml', + 'csharp': 'dotnet.yml', + 'c#': 'dotnet.yml', + 'kotlin': 'kotlin.yml', + 'scala': 'scala.yml', + 'swift': 'swift.yml', + 'rust': 'rust.yml', + 'elixir': 'elixir.yml', + 'erlang': 'erlang.yml', + 'objective-c': 'objective-c.yml', + } + + def __init__(self, custom_rules_path: Path): + """Initialize the custom rules builder. + + Args: + custom_rules_path: Path to the directory containing custom rule files + """ + self.custom_rules_path = custom_rules_path + self.temp_dir: Optional[Path] = None + + def build_rule_files(self, enabled_languages: List[str]) -> Dict[str, Path]: + """Build custom rule files from custom rules directory. + + Args: + enabled_languages: List of enabled language rule files (e.g., ['python.yml', 'javascript_typescript.yml']) + + Returns: + Dictionary mapping rule file names to temporary file paths containing custom rules. + Empty dict if no custom rules found for enabled languages. + """ + # Group custom rules by target rule file + rules_by_file = self._collect_rules_by_file(enabled_languages) + + if not rules_by_file: + logger.info("No custom rules found for enabled languages") + return {} + + # Create temporary directory for custom rule files + self.temp_dir = Path(tempfile.mkdtemp(prefix='socket_custom_rules_')) + logger.info(f"Creating custom rule files in {self.temp_dir}") + + # Write temporary rule files + return self._write_rule_files(rules_by_file) + + def _collect_rules_by_file(self, enabled_languages: List[str]) -> Dict[str, List[Dict[str, Any]]]: + """Scan custom rules directory and group rules by target rule file. + + Args: + enabled_languages: List of enabled language rule files + + Returns: + Dictionary mapping rule file names to lists of rules + """ + rules_by_file: Dict[str, List[Dict[str, Any]]] = {} + + # Find all YAML files recursively + yaml_files = list(self.custom_rules_path.rglob('*.yml')) + list(self.custom_rules_path.rglob('*.yaml')) + logger.info(f"Found {len(yaml_files)} custom rule files in {self.custom_rules_path}") + + for yaml_file in yaml_files: + try: + rules = self._parse_rule_file(yaml_file) + self._categorize_rules(rules, enabled_languages, rules_by_file) + except Exception as e: + logger.warning(f"Failed to process custom rule file {yaml_file}: {e}") + continue + + return rules_by_file + + def _parse_rule_file(self, yaml_file: Path) -> List[Dict[str, Any]]: + """Parse a YAML rule file and extract rules. + + Args: + yaml_file: Path to the YAML file + + Returns: + List of rule dictionaries + """ + with open(yaml_file, 'r', encoding='utf-8') as f: + data = yaml.safe_load(f) + + if not data or 'rules' not in data: + return [] + + rules = data.get('rules', []) + if not isinstance(rules, list): + return [] + + return [rule for rule in rules if isinstance(rule, dict)] + + def _categorize_rules( + self, + rules: List[Dict[str, Any]], + enabled_languages: List[str], + rules_by_file: Dict[str, List[Dict[str, Any]]] + ) -> None: + """Categorize rules by target rule file based on their languages. + + Args: + rules: List of rule dictionaries to categorize + enabled_languages: List of enabled language rule files + rules_by_file: Dictionary to populate with categorized rules (modified in place) + """ + for rule in rules: + # Get languages this rule applies to + rule_languages = rule.get('languages', []) + if not rule_languages: + continue + + # Determine which Socket rule file(s) this rule should go into + target_files = self._determine_target_files(rule_languages, enabled_languages) + + # Add rule to each target file + for target_file in target_files: + if target_file not in rules_by_file: + rules_by_file[target_file] = [] + rules_by_file[target_file].append(rule) + + def _determine_target_files(self, rule_languages: List[str], enabled_languages: List[str]) -> set: + """Determine which rule files a rule should be added to. + + Args: + rule_languages: Languages specified in the rule + enabled_languages: List of enabled language rule files + + Returns: + Set of target rule file names + """ + target_files = set() + + for lang in rule_languages: + lang_lower = str(lang).lower() + if lang_lower in self.LANGUAGE_TO_RULE_FILE: + target_file = self.LANGUAGE_TO_RULE_FILE[lang_lower] + # Only include if this language is enabled + if target_file in enabled_languages: + target_files.add(target_file) + + return target_files + + def _write_rule_files(self, rules_by_file: Dict[str, List[Dict[str, Any]]]) -> Dict[str, Path]: + """Write custom rule files to temporary directory. + + Args: + rules_by_file: Dictionary mapping rule file names to lists of rules + + Returns: + Dictionary mapping rule file names to temporary file paths + """ + if not self.temp_dir: + raise RuntimeError("Temporary directory not initialized") + + custom_rule_paths: Dict[str, Path] = {} + + for rule_file_name, rules in rules_by_file.items(): + temp_file_path = self.temp_dir / rule_file_name + rule_data = {'rules': rules} + + try: + with open(temp_file_path, 'w', encoding='utf-8') as f: + yaml.dump(rule_data, f, default_flow_style=False, sort_keys=False) + + custom_rule_paths[rule_file_name] = temp_file_path + logger.info(f"Created custom rule file {rule_file_name} with {len(rules)} rules") + except Exception as e: + logger.error(f"Failed to write custom rule file {temp_file_path}: {e}") + continue + + return custom_rule_paths + + def cleanup(self) -> None: + """Clean up temporary rule files (optional, as temp files are typically auto-cleaned).""" + if self.temp_dir and self.temp_dir.exists(): + try: + import shutil + shutil.rmtree(self.temp_dir) + logger.debug(f"Cleaned up temporary rule directory: {self.temp_dir}") + except Exception as e: + logger.warning(f"Failed to clean up temporary rule directory {self.temp_dir}: {e}") diff --git a/socket_basics/core/connector/socket_tier1/scanner.py b/socket_basics/core/connector/socket_tier1/scanner.py index b7e764e..12f8b9a 100644 --- a/socket_basics/core/connector/socket_tier1/scanner.py +++ b/socket_basics/core/connector/socket_tier1/scanner.py @@ -105,16 +105,21 @@ def scan(self) -> Dict[str, Any]: if not auth_env.get('SOCKET_ORG') or not auth_env.get('SOCKET_SECURITY_API_KEY'): raise ConnectorExecutionError('Socket Tier 1 scanner requires SOCKET_ORG and SOCKET_SECURITY_API_KEY or SOCKET_SECURITY_API_TOKEN to be set') + # Find socket executable + socket_exe = shutil.which('socket') + if not socket_exe: + raise ConnectorExecutionError('Socket CLI executable not found in PATH. Ensure "socket" is installed.') + # Build command additional = self._parse_additional_params() # Default target is current dir target = '.' - cmd = ['socket', 'scan', 'reach', '--org', auth_env['SOCKET_ORG'], '.'] + cmd = [socket_exe, 'scan', 'reach', '--org', auth_env['SOCKET_ORG'], '.'] # Add additional options before the target if they look like flags # To be safe, append all additional params before target if additional: # remove target and rebuild: socket scan reach --org [additional...] . - cmd = ['socket', 'scan', 'reach', '--org', auth_env['SOCKET_ORG']] + additional + ['.'] + cmd = [socket_exe, 'scan', 'reach', '--org', auth_env['SOCKET_ORG']] + additional + ['.'] logger.info('Running Socket Tier1 reachability: %s', ' '.join(shlex.quote(p) for p in cmd)) diff --git a/socket_basics/socket_basics.py b/socket_basics/socket_basics.py index 17ee51d..4a1c96f 100644 --- a/socket_basics/socket_basics.py +++ b/socket_basics/socket_basics.py @@ -303,15 +303,13 @@ def submit_socket_facts(self, socket_facts_path: Path, results: Dict[str, Any]) try: res = sdk.fullscans.post( - [ - "./.socket.facts.json"], - base_path="./", - params=params, - use_types=True, - use_lazy_loading=True, - max_open_files=50, - base_paths=[str(self.config.workspace) - ] + [str(absolute_socket_facts_path)], + base_path=str(socket_facts_path.parent.absolute()), + params=params, + use_types=True, + use_lazy_loading=True, + max_open_files=50, + base_paths=[str(self.config.workspace)] ) logger.debug(f"✓ SDK call completed") logger.debug(f"SDK response type: {type(res)}") @@ -378,6 +376,12 @@ def main(): try: out_arg = getattr(args, 'output', '.socket.facts.json') or '.socket.facts.json' out_path = Path(out_arg) + + # If output path is relative and workspace is specified, make it relative to workspace + if not out_path.is_absolute() and hasattr(args, 'workspace') and args.workspace: + workspace_path = Path(args.workspace) + out_path = workspace_path / out_path + # If file exists, remove it to ensure fresh start if out_path.exists(): out_path.unlink() diff --git a/socket_basics/version.py b/socket_basics/version.py index 9eb1ebe..bd538f7 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.11" +__version__ = "1.0.12" From 8ff44bf20a73957735bbd32f010aebaa5332c8b5 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 01:50:28 -0700 Subject: [PATCH 2/9] Updated default javascript rules --- README.md | 10 +- docs/github-action.md | 38 +- docs/local-install-docker.md | 70 +- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/connectors.yaml | 2 +- socket_basics/core/config.py | 21 +- .../core/connector/opengrep/__init__.py | 92 +- socket_basics/rules/javascript_typescript.yml | 1295 ++++++++++++++--- socket_basics/socket_basics.py | 7 +- socket_basics/version.py | 2 +- 11 files changed, 1196 insertions(+), 345 deletions(-) diff --git a/README.md b/README.md index a6687a3..63a920c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.12 + uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.12 . +docker build -t socketdev/socket-basics:1.0.13 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.12 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.13 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index 18fa0bb..c90a864 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.12 + uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.12 +> - uses: SocketDev/socket-basics@1.0.13 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.12 +- uses: SocketDev/socket-basics@1.0.13 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.12 + uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.12 + uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.12:${{ github.sha }} . + run: docker build -t myapp:1.0.13:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.12 + uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.12 + uses: SocketDev/socket-basics@1.0.13 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.12 + - uses: SocketDev/socket-basics@1.0.13 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 71bd0be..d57d73c 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.12 . +docker build -t socket-basics:1.0.13 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.12 . +docker build -t socket-basics:1.0.13 . # Or build with latest tag -docker build -t socket-basics:1.0.12:latest . +docker build -t socket-basics:1.0.13:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.12 . +docker build -t myorg/security-scanner:1.0.13 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.12 . +docker build --platform linux/amd64 -t socket-basics:1.0.13 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.12 socket-basics --version -docker run --rm socket-basics:1.0.12 socket --version -docker run --rm socket-basics:1.0.12 trivy --version -docker run --rm socket-basics:1.0.12 semgrep --version -docker run --rm socket-basics:1.0.12 trufflehog --version +docker run --rm socket-basics:1.0.13 socket-basics --version +docker run --rm socket-basics:1.0.13 socket --version +docker run --rm socket-basics:1.0.13 trivy --version +docker run --rm socket-basics:1.0.13 semgrep --version +docker run --rm socket-basics:1.0.13 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.12 + socket-basics:1.0.13 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.12').inside( + docker.image('socket-basics:1.0.13').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.12 + image: socket-basics:1.0.13 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.12 + socket-basics:1.0.13 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.12 + socket-basics:1.0.13 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.12 \ + socket-basics:1.0.13 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.12 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.13 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.12 .' +alias sb-build='docker build -t socket-basics:1.0.13 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.12" +IMAGE_NAME="socket-basics:1.0.13" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 985cbb5..29ecdce 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.12 . +docker build -t socket-basics:1.0.13 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index ad1983e..2a1c26a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.12" +version = "1.0.13" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/connectors.yaml b/socket_basics/connectors.yaml index 5dbe263..e2ffd47 100644 --- a/socket_basics/connectors.yaml +++ b/socket_basics/connectors.yaml @@ -184,7 +184,7 @@ connectors: description: "Comma-separated list of JavaScript/TypeScript SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_JAVASCRIPT_ENABLED_RULES type: str - default: "js-eval-usage,js-sql-injection,js-command-injection,js-prototype-pollution,js-xss-innerhtml,js-path-traversal,js-tls-reject-unauthorized-false,js-weak-crypto-md5" + default: "js-code-injection-eval,js-sql-injection,js-nosql-injection,js-command-injection,js-ldap-injection,js-prototype-pollution,js-xss-innerhtml,js-dom-xss,js-path-traversal,js-open-redirect,js-cors-allow-all,js-weak-hash-md5,js-weak-hash-sha1,js-insecure-random,js-hardcoded-secret,js-weak-cipher,js-tls-reject-unauthorized-false,js-insecure-tls-version,js-jwt-no-verify,js-weak-jwt-secret,js-weak-session-cookie,js-default-credentials,js-error-stack-exposed,js-unsafe-deserialization,js-ssrf-vulnerability,js-react-dangerous-html,js-unsafe-buffer,js-unsafe-file-operations,js-unsafe-process-spawn,js-unvalidated-file-upload,js-debugger-statement,js-parseint-missing-radix" - name: javascript_disabled_rules option: --javascript-disabled-rules description: "Comma-separated list of JavaScript/TypeScript SAST rules to disable" diff --git a/socket_basics/core/config.py b/socket_basics/core/config.py index aacfd0f..b2beed6 100644 --- a/socket_basics/core/config.py +++ b/socket_basics/core/config.py @@ -1008,7 +1008,16 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict if socket_basics_config: # Normalize camelCase API keys to snake_case internal format normalized_config = normalize_api_config(socket_basics_config) - config.update(normalized_config) + # Filter out empty strings for rule configs - treat them as unset to use code defaults + # Only filter string values ending with _enabled_rules or _disabled_rules + filtered_config = {} + for k, v in normalized_config.items(): + if isinstance(v, str) and v == '' and (k.endswith('_enabled_rules') or k.endswith('_disabled_rules')): + # Skip empty rule config strings - they'll fall back to defaults + logger.debug(f"Filtering out empty rule config: {k}") + continue + filtered_config[k] = v + config.update(filtered_config) logging.getLogger(__name__).info("Loaded Socket Basics API configuration (overrides environment defaults)") else: logger.debug(" No Socket Basics API config loaded") @@ -1018,7 +1027,15 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict if json_config: # Also normalize JSON config in case it comes from API normalized_json = normalize_api_config(json_config) - config.update(normalized_json) + # Filter out empty strings for rule configs - treat them as unset to use code defaults + filtered_json = {} + for k, v in normalized_json.items(): + if isinstance(v, str) and v == '' and (k.endswith('_enabled_rules') or k.endswith('_disabled_rules')): + # Skip empty rule config strings - they'll fall back to defaults + logger.debug(f"Filtering out empty rule config: {k}") + continue + filtered_json[k] = v + config.update(filtered_json) logging.getLogger(__name__).info("Loaded JSON configuration (overrides environment defaults)") # Note: CLI arguments are handled separately and take highest priority diff --git a/socket_basics/core/connector/opengrep/__init__.py b/socket_basics/core/connector/opengrep/__init__.py index cb234b0..e0a4bd0 100644 --- a/socket_basics/core/connector/opengrep/__init__.py +++ b/socket_basics/core/connector/opengrep/__init__.py @@ -87,20 +87,23 @@ def scan(self) -> Dict[str, Any]: config_args: List[str] = [] # Build config_args using custom rules where available, falling back to bundled rules - if filtered: - # When specific rules are enabled, use filtered approach - for rf, enabled_ids in filtered.items(): - # Check if we have a custom rule file for this language - if custom_rule_files and rf in custom_rule_files: - p = custom_rule_files[rf] - logger.info(f"Using custom rules for {rf}") - else: - # Fall back to bundled rules - p = Path(rules_dir) / rf - if not p.exists(): - logger.debug('Rule file missing: %s', p) - continue - + # Process all enabled languages - use filtered rules if specified, otherwise use all rules + for rf in rule_files: + # Check if we have a custom rule file for this language + if custom_rule_files and rf in custom_rule_files: + p = custom_rule_files[rf] + logger.info(f"Using custom rules for {rf}") + else: + # Fall back to bundled rules + p = Path(rules_dir) / rf + if not p.exists(): + logger.debug('Rule file missing: %s', p) + continue + + # Check if this language has specific rules enabled (filtered mode) + if filtered and rf in filtered: + enabled_ids = filtered[rf] + logger.debug(f"Using filtered rules for {rf}: {len(enabled_ids)} rules enabled") try: with open(p, 'r') as fh: data = yaml.safe_load(fh) or {} @@ -111,22 +114,10 @@ def scan(self) -> Dict[str, Any]: config_args.extend(['--exclude-rule', ex]) except Exception: logger.debug('Failed reading/parsing rule file %s', p, exc_info=True) - else: - # No filtering - use entire rule files - for rf in rule_files: - # Check if we have a custom rule file for this language - if custom_rule_files and rf in custom_rule_files: - p = custom_rule_files[rf] - logger.info(f"Using custom rules for {rf}") - config_args.extend(['--config', str(p)]) - else: - # Fall back to bundled rules - p = Path(rules_dir) / rf - if p.exists(): - logger.debug(f"Using bundled rules for {rf}") - config_args.extend(['--config', str(p)]) - else: - logger.warning(f"No rules found for {rf} (neither custom nor bundled)") + else: + # No specific rules configured - use all rules from this file + logger.debug(f"Using all rules for {rf}") + config_args.extend(['--config', str(p)]) # If nothing selected, only include all bundled rule files when the # caller explicitly requested all languages or all rules. Otherwise @@ -407,15 +398,44 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: comps[comp_id]['alerts'].append(alert) except Exception: logger.debug('Failed to convert single opengrep result to alert', exc_info=True) + + # Now add components for ALL files in the workspace (even those without alerts) + try: + from ...config import discover_all_files + import hashlib as _hash + from pathlib import Path as _P + + workspace = getattr(self.config, 'workspace', None) + if workspace: + all_files = discover_all_files(str(workspace), respect_gitignore=True) + logger.debug(f"Discovered {len(all_files)} files in workspace for component generation") + + for file_path in all_files: + # Normalize path and generate component ID (same logic as above) + try: + norm = file_path.replace('\\', '/') # Normalize to forward slashes + comp_id = _hash.sha256(norm.encode('utf-8')).hexdigest() + + # Only add if not already present (files with alerts already have components) + if comp_id not in comps: + comps[comp_id] = { + 'id': comp_id, + 'type': 'generic', + 'subPath': 'sast-generic', + 'name': file_path, + "internal": True, + 'alerts': [] + } + except Exception: + logger.debug(f'Failed to create component for file: {file_path}', exc_info=True) + except Exception as e: + logger.debug(f'Failed to discover all workspace files: {e}', exc_info=True) + return comps - # If it's already a mapping of component_id -> component, filter empty alerts + # If it's already a mapping of component_id -> component, return all (not just with alerts) if all(isinstance(v, dict) for v in raw_results.values()): - for k, v in raw_results.items(): - alerts = v.get('alerts') or [] - if alerts: - out[k] = v - return out + return raw_results return {} diff --git a/socket_basics/rules/javascript_typescript.yml b/socket_basics/rules/javascript_typescript.yml index f9973dc..60f8ddf 100644 --- a/socket_basics/rules/javascript_typescript.yml +++ b/socket_basics/rules/javascript_typescript.yml @@ -1,433 +1,1248 @@ rules: - # === Critical Severity Rules === - + # ===================================================================== + # OWASP Top 10 2021 Coverage for JavaScript/TypeScript + # ===================================================================== + + # ===================================================================== + # A01:2021 - Broken Access Control + # ===================================================================== + + # Missing authorization checks + - id: js-missing-auth-check + message: "Route handler missing authentication/authorization check" + severity: HIGH + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: | + $APP.$METHOD($PATH, async ($REQ, $RES) => { + ... + }) + - pattern: | + $APP.$METHOD($PATH, ($REQ, $RES) => { + ... + }) + - pattern-not-inside: | + ... + if ($REQ.user) { ... } + ... + - pattern-not-inside: | + ... + if ($REQ.isAuthenticated()) { ... } + ... + - metavariable-regex: + metavariable: $METHOD + regex: (post|put|delete|patch) + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-862 + confidence: low + subcategory: access-control + + # Insecure direct object reference + - id: js-idor-vulnerability + message: "Potential IDOR vulnerability - user input directly used to access resources" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: "$DB.find({ id: $REQ.params.id })" + - pattern: $DB.findById($REQ.params.id) + - pattern: "$DB.findOne({ _id: $REQ.params.id })" + - pattern: fs.readFile($REQ.params.file, ...) + - pattern: fs.readFileSync($REQ.params.file) + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-639 + confidence: medium + subcategory: access-control + + # Path traversal + - id: js-path-traversal + message: "Path traversal vulnerability - user input used in file operations" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: fs.readFile($PATH + $USER_INPUT, ...) + - pattern: fs.readFileSync($PATH + $USER_INPUT) + - pattern: fs.writeFile($PATH + $USER_INPUT, ...) + - pattern: fs.writeFileSync($PATH + $USER_INPUT, ...) + - pattern: fs.createReadStream($PATH + $USER_INPUT) + - pattern: fs.createWriteStream($PATH + $USER_INPUT) + - pattern: fs.readFile(`${$PATH}${$USER_INPUT}`, ...) + - pattern: fs.readFileSync(`${$PATH}${$USER_INPUT}`) + - pattern: require($USER_INPUT) + - pattern: import($USER_INPUT) + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-22 + confidence: high + subcategory: access-control + + # Unvalidated redirect + - id: js-open-redirect + message: "Open redirect vulnerability - user input used in redirect without validation" + severity: MEDIUM + languages: [javascript, typescript] + pattern-either: + - pattern: res.redirect($REQ.query.$PARAM) + - pattern: res.redirect($REQ.params.$PARAM) + - pattern: res.redirect($REQ.body.$PARAM) + - pattern: window.location = $USER_INPUT + - pattern: window.location.href = $USER_INPUT + - pattern: document.location = $USER_INPUT + - pattern: document.location.href = $USER_INPUT + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-601 + confidence: medium + subcategory: access-control + + # CORS misconfiguration + - id: js-cors-allow-all + message: "CORS configured to allow all origins - security risk" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: | + cors({ origin: "*" }) + - pattern: | + $RES.setHeader("Access-Control-Allow-Origin", "*") + - pattern: | + $RES.header("Access-Control-Allow-Origin", "*") + metadata: + category: security + owasp: "A01:2021" + cwe: CWE-942 + confidence: high + subcategory: access-control + + # ===================================================================== + # A02:2021 - Cryptographic Failures + # ===================================================================== + + # Weak cryptographic hash algorithms + - id: js-weak-hash-md5 + message: "MD5 is cryptographically broken and should not be used" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: crypto.createHash("md5") + - pattern: crypto.createHash('md5') + - pattern: require('md5') + - pattern: import ... from 'md5' + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + - id: js-weak-hash-sha1 + message: "SHA1 is cryptographically weak and should not be used for security" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: crypto.createHash("sha1") + - pattern: crypto.createHash('sha1') + - pattern: require('sha1') + - pattern: import ... from 'sha1' + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + # Insecure random number generation + - id: js-insecure-random + message: "Math.random() is not cryptographically secure - use crypto.randomBytes() instead" + severity: HIGH + languages: [javascript, typescript] + pattern: Math.random() + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-338 + confidence: high + subcategory: crypto + fix: "Use crypto.randomBytes() or crypto.getRandomValues() for security-sensitive operations" + + # Hardcoded secrets and credentials + - id: js-hardcoded-secret + message: "Hardcoded secret or credential detected - use environment variables" + severity: HIGH + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: const $VAR = "..." + - pattern: let $VAR = "..." + - pattern: var $VAR = "..." + - metavariable-regex: + metavariable: $VAR + regex: (?i)(password|passwd|pwd|secret|token|api_key|apikey|private_key|access_token|auth_token|session_key|encryption_key) + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-798 + confidence: medium + subcategory: crypto + + # Weak cipher algorithms + - id: js-weak-cipher + message: "Weak cipher algorithm detected - use AES-256-GCM or ChaCha20-Poly1305" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: crypto.createCipher("des", ...) + - pattern: crypto.createCipher("des-ede", ...) + - pattern: crypto.createCipher("des-ede-cbc", ...) + - pattern: crypto.createCipher("des3", ...) + - pattern: crypto.createCipher("rc4", ...) + - pattern: crypto.createCipher("rc2", ...) + - pattern: crypto.createCipher("blowfish", ...) + - pattern: crypto.createCipheriv("des", ...) + - pattern: crypto.createCipheriv("rc4", ...) + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + # TLS/SSL certificate validation disabled + - id: js-tls-reject-unauthorized-false + message: "TLS certificate validation disabled - vulnerable to MITM attacks" + severity: CRITICAL + languages: [javascript, typescript] + pattern-either: + - pattern: process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" + - pattern: process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' + - pattern: process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0" + - pattern: | + { ..., rejectUnauthorized: false, ... } + - pattern: | + axios.create({ ..., rejectUnauthorized: false, ... }) + - pattern: | + https.request({ ..., rejectUnauthorized: false, ... }) + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-295 + confidence: high + subcategory: crypto + + # Insecure TLS versions + - id: js-insecure-tls-version + message: "Insecure TLS version - use TLS 1.2 or higher" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: | + { ..., secureProtocol: "SSLv2_method", ... } + - pattern: | + { ..., secureProtocol: "SSLv3_method", ... } + - pattern: | + { ..., secureProtocol: "TLSv1_method", ... } + - pattern: | + { ..., secureProtocol: "TLSv1_1_method", ... } + - pattern: | + tls.createSecureContext({ ..., secureProtocol: "SSLv3_method", ... }) + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-327 + confidence: high + subcategory: crypto + + # Missing encryption in transit + - id: js-insecure-protocol + message: "HTTP used instead of HTTPS - data transmitted in cleartext" + severity: MEDIUM + languages: [javascript, typescript] + pattern-either: + - pattern: require("http").createServer(...) + - pattern: http.createServer(...) + - pattern: | + fetch("http://...") + - pattern: | + axios.get("http://...") + - pattern: | + axios.post("http://...") + metadata: + category: security + owasp: "A02:2021" + cwe: CWE-319 + confidence: low + subcategory: crypto + + # ===================================================================== + # A03:2021 - Injection + # ===================================================================== + # Code injection via eval - - id: js-eval-usage - message: "Use of eval() detected. This can execute arbitrary code and is extremely dangerous" + - id: js-code-injection-eval + message: "Code injection via eval() - can execute arbitrary code" severity: CRITICAL languages: [javascript, typescript] pattern-either: - pattern: eval($EXPR) + - pattern: eval($REQ.$PROP) - pattern: Function($ARGS) - - pattern: setTimeout($CODE, ...) - - pattern: setInterval($CODE, ...) - where: - - metavariable-pattern: - metavariable: $CODE - pattern: "..." + - pattern: new Function($ARGS) + - pattern: setTimeout($CODE_STR, ...) + - pattern: setInterval($CODE_STR, ...) + - pattern: vm.runInNewContext($CODE) + - pattern: vm.runInThisContext($CODE) metadata: category: security + owasp: "A03:2021" cwe: CWE-94 confidence: high + subcategory: injection # SQL injection - id: js-sql-injection - message: "Possible SQL injection via string concatenation or template literals" + message: "SQL injection vulnerability - use parameterized queries" severity: CRITICAL languages: [javascript, typescript] pattern-either: - pattern: $DB.query("..." + $VAR + "...") - - pattern: $DB.execute("..." + $VAR + "...") - - pattern: $DB.raw("..." + $VAR + "...") - pattern: $DB.query(`...${$VAR}...`) + - pattern: $DB.execute("..." + $VAR + "...") - pattern: $DB.execute(`...${$VAR}...`) + - pattern: $DB.raw("..." + $VAR + "...") + - pattern: $DB.raw(`...${$VAR}...`) + - pattern: $CONN.query("..." + $REQ.$PROP + "...") + - pattern: $CONN.query(`...${$REQ.$PROP}...`) + - pattern: mysql.query("..." + $VAR + "...") + - pattern: pg.query("..." + $VAR + "...") metadata: category: security + owasp: "A03:2021" cwe: CWE-89 confidence: high + subcategory: injection + + # NoSQL injection (MongoDB) + - id: js-nosql-injection + message: "NoSQL injection vulnerability - validate and sanitize user input" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: $COLLECTION.find($REQ.query) + - pattern: $COLLECTION.find($REQ.body) + - pattern: $COLLECTION.findOne($REQ.query) + - pattern: $COLLECTION.findOne($REQ.body) + - pattern: $COLLECTION.update($REQ.query, ...) + - pattern: $COLLECTION.update($REQ.body, ...) + - pattern: $COLLECTION.remove($REQ.query) + - pattern: $COLLECTION.deleteOne($REQ.query) + - pattern: $COLLECTION.deleteMany($REQ.query) + - pattern: "$MODEL.find({ ..., $FIELD: $REQ.query.$PARAM, ... })" + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-943 + confidence: high + subcategory: injection # Command injection - id: js-command-injection - message: "Command injection detected via child_process functions" + message: "Command injection vulnerability - avoid shell execution with user input" severity: CRITICAL languages: [javascript, typescript] pattern-either: - pattern: child_process.exec($CMD + $VAR) - - pattern: child_process.spawn($CMD, [$ARGS, ..., $VAR, ...]) + - pattern: child_process.exec(`${$CMD}${$VAR}`) + - pattern: child_process.exec($REQ.$PROP) + - pattern: cp.exec($CMD + $VAR) - pattern: require('child_process').exec($CMD + $VAR) - - pattern: exec($CMD + $VAR) + - pattern: execSync($CMD + $VAR) + - pattern: child_process.execSync($CMD + $VAR) + - pattern: "child_process.spawn($CMD, ..., { shell: true })" metadata: category: security + owasp: "A03:2021" cwe: CWE-78 confidence: high + subcategory: injection - # Prototype pollution - - id: js-prototype-pollution - message: "Potential prototype pollution vulnerability" - severity: CRITICAL + # LDAP injection + - id: js-ldap-injection + message: "LDAP injection vulnerability - sanitize user input in LDAP queries" + severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: $OBJ["__proto__"] = $VAL - - pattern: $OBJ.__proto__ = $VAL - - pattern: $OBJ["constructor"] = $VAL - - pattern: $OBJ.constructor = $VAL - - pattern: Object.setPrototypeOf($OBJ, $PROTO) + - pattern: $CLIENT.search($FILTER + $USER_INPUT, ...) + - pattern: $CLIENT.search(`${$FILTER}${$USER_INPUT}`, ...) + - pattern: $CLIENT.bind($DN + $USER_INPUT, ...) + - pattern: $CLIENT.bind(`${$DN}${$USER_INPUT}`, ...) metadata: category: security - cwe: CWE-1321 - confidence: medium - - # === High Severity Rules === + owasp: "A03:2021" + cwe: CWE-90 + confidence: high + subcategory: injection # XSS via innerHTML - id: js-xss-innerhtml - message: "XSS vulnerability via innerHTML with unsanitized data" + message: "XSS vulnerability via innerHTML - use textContent or sanitize input" severity: HIGH languages: [javascript, typescript] pattern-either: - pattern: $ELEMENT.innerHTML = $VAR - pattern: $ELEMENT.outerHTML = $VAR + - pattern: $ELEMENT.insertAdjacentHTML(..., $VAR) - pattern: document.write($VAR) - pattern: document.writeln($VAR) - where: - - metavariable-pattern: - metavariable: $VAR - pattern: $USER_INPUT metadata: category: security + owasp: "A03:2021" cwe: CWE-79 confidence: medium + subcategory: injection - # Hardcoded secrets - - id: js-hardcoded-secrets - message: "Hardcoded secret or API key detected" + # DOM-based XSS + - id: js-dom-xss + message: "DOM XSS vulnerability - validate and sanitize before using in DOM" severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: const $VAR = "..." - - pattern: let $VAR = "..." - - pattern: var $VAR = "..." - - pattern: $OBJ.$PROP = "..." - where: - - metavariable-regex: - metavariable: $VAR - regex: (?i).*(api_key|apikey|secret|token|password|passwd|pwd|private_key|access_token).* - - metavariable-regex: - metavariable: $PROP - regex: (?i).*(api_key|apikey|secret|token|password|passwd|pwd|private_key|access_token).* + - pattern: $ELEMENT.setAttribute("href", $USER_INPUT) + - pattern: $ELEMENT.setAttribute("src", $USER_INPUT) + - pattern: $ELEMENT.setAttribute("action", $USER_INPUT) + - pattern: $ELEMENT.setAttribute("formaction", $USER_INPUT) + - pattern: $ELEMENT.src = $USER_INPUT + - pattern: $ELEMENT.href = $USER_INPUT + - pattern: location = $USER_INPUT + - pattern: location.href = $USER_INPUT metadata: category: security - cwe: CWE-798 + owasp: "A03:2021" + cwe: CWE-79 confidence: medium + subcategory: injection - # Path traversal - - id: js-path-traversal - message: "Path traversal vulnerability detected" + # XXE (XML External Entity) + - id: js-xxe-vulnerability + message: "XXE vulnerability - disable external entity processing in XML parser" + severity: HIGH + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: new DOMParser().parseFromString($XML, "text/xml") + - pattern: libxmljs.parseXml($XML) + - pattern: xml2js.parseString($XML, ...) + - pattern: parser.parseFromString($XML, ...) + - pattern-not-inside: | + ... + noent: false + ... + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-611 + confidence: medium + subcategory: injection + + # Server-side template injection + - id: js-template-injection + message: "Template injection vulnerability - sanitize user input in templates" severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: fs.readFile($PATH + $USER_INPUT) - - pattern: fs.readFileSync($PATH + $USER_INPUT) - - pattern: fs.writeFile($PATH + $USER_INPUT, ...) - - pattern: fs.createReadStream($PATH + $USER_INPUT) - - pattern: path.join($BASE, $USER_INPUT) + - pattern: eval($TEMPLATE_STR) + - pattern: | + $TEMPLATE_ENGINE.render($TEMPLATE, { ..., userInput: $REQ.$PROP, ... }) + - pattern: | + _.template($USER_INPUT) + - pattern: | + Handlebars.compile($USER_INPUT) metadata: category: security - cwe: CWE-22 + owasp: "A03:2021" + cwe: CWE-1336 confidence: medium + subcategory: injection - # Insecure random - - id: js-insecure-random - message: "Math.random() is not cryptographically secure" + # Prototype pollution + - id: js-prototype-pollution + message: "Prototype pollution vulnerability - can lead to arbitrary code execution" + severity: CRITICAL + languages: [javascript, typescript] + pattern-either: + - pattern: $OBJ["__proto__"] = $VAL + - pattern: $OBJ.__proto__ = $VAL + - pattern: $OBJ["constructor"]["prototype"] = $VAL + - pattern: $OBJ.constructor.prototype = $VAL + - pattern: Object.setPrototypeOf($OBJ, $PROTO) + - pattern: $OBJ[$KEY] = $VAL + metadata: + category: security + owasp: "A03:2021" + cwe: CWE-1321 + confidence: medium + subcategory: injection + + # ===================================================================== + # A04:2021 - Insecure Design + # ===================================================================== + + # Missing rate limiting + - id: js-missing-rate-limit + message: "Route missing rate limiting - vulnerable to brute force attacks" + severity: MEDIUM + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: | + $APP.post("/login", ...) + - pattern: | + $APP.post("/api/login", ...) + - pattern: | + $APP.post("*/login", ...) + - pattern-not-inside: | + ... + rateLimit(...) + ... + metadata: + category: security + owasp: "A04:2021" + cwe: CWE-307 + confidence: low + subcategory: design + + # Insufficient input validation + - id: js-missing-input-validation + message: "User input used without validation" + severity: MEDIUM + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: $DB.find($REQ.query) + - pattern: $DB.findOne($REQ.params) + - pattern: $FS.readFile($REQ.body.$PROP, ...) + - pattern-not-inside: | + ... + if (typeof $REQ.$PROP === ...) { ... } + ... + - pattern-not-inside: | + ... + validator.validate(...) + ... + metadata: + category: security + owasp: "A04:2021" + cwe: CWE-20 + confidence: low + subcategory: design + + # Predictable resource location + - id: js-predictable-resource + message: "Predictable resource identifiers - use UUIDs instead of sequential IDs" + severity: LOW + languages: [javascript, typescript] + pattern-either: + - pattern: | + $VAR = $NUM++ + - pattern: | + $OBJ.id = $COUNTER++ + - pattern: | + uuid.v1() + metadata: + category: security + owasp: "A04:2021" + cwe: CWE-330 + confidence: low + subcategory: design + + # ===================================================================== + # A05:2021 - Security Misconfiguration + # ===================================================================== + + # Debug mode enabled + - id: js-debug-mode-enabled + message: "Debug mode enabled in production - exposes sensitive information" severity: HIGH languages: [javascript, typescript] - pattern: Math.random() + pattern-either: + - pattern: | + { ..., debug: true, ... } + - pattern: process.env.NODE_ENV = "development" + - pattern: app.set("env", "development") metadata: category: security - cwe: CWE-338 + owasp: "A05:2021" + cwe: CWE-489 + confidence: medium + subcategory: configuration + + # Debugger statement in code + - id: js-debugger-statement + message: "Debugger statement should not be in production code" + severity: LOW + languages: [javascript, typescript] + pattern: debugger + metadata: + category: security + owasp: "A05:2021" + cwe: CWE-489 confidence: high + subcategory: configuration - # TLS/SSL bypass - - id: js-tls-reject-unauthorized-false - message: "TLS certificate validation disabled" + # Weak session configuration + - id: js-weak-session-cookie + message: "Insecure session cookie configuration" severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" - - pattern: process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0" - - pattern: $AGENT.options.rejectUnauthorized = false + - pattern: | + session({ ..., secure: false, ... }) + - pattern: | + session({ ..., httpOnly: false, ... }) + - pattern: | + session({ ..., sameSite: false, ... }) + - pattern: | + session({ ..., sameSite: "none", ... }) + - pattern: | + $RES.cookie($NAME, $VAL, { ..., secure: false, ... }) + - pattern: | + $RES.cookie($NAME, $VAL, { ..., httpOnly: false, ... }) metadata: category: security - cwe: CWE-295 + owasp: "A05:2021" + cwe: CWE-614 confidence: high + subcategory: configuration - # === Medium Severity Rules === + # Missing security headers (Helmet.js) + - id: js-missing-helmet + message: "Express app missing Helmet.js security headers middleware" + severity: MEDIUM + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: const $APP = express() + - pattern: var $APP = express() + - pattern: let $APP = express() + - pattern-not-inside: | + ... + $APP.use(helmet(...)) + ... + metadata: + category: security + owasp: "A05:2021" + cwe: CWE-693 + confidence: low + subcategory: configuration - # Weak crypto algorithms - - id: js-weak-crypto-md5 - message: "Use of weak MD5 hash algorithm" + # Error stack traces exposed + - id: js-error-stack-exposed + message: "Error stack trace exposed to client - can leak sensitive information" severity: MEDIUM languages: [javascript, typescript] pattern-either: - - pattern: crypto.createHash("md5") - - pattern: crypto.createHash('md5') - - pattern: require('md5')($DATA) - - pattern: md5($DATA) + - pattern: $RES.send($ERR.stack) + - pattern: "$RES.json({ ..., stack: $ERR.stack, ... })" + - pattern: $RES.status(...).send($ERR) metadata: category: security - cwe: CWE-327 + owasp: "A05:2021" + cwe: CWE-209 confidence: high + subcategory: configuration - - id: js-weak-crypto-sha1 - message: "Use of weak SHA1 hash algorithm" - severity: MEDIUM + # Default credentials + - id: js-default-credentials + message: "Default or weak credentials detected" + severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: crypto.createHash("sha1") - - pattern: crypto.createHash('sha1') - - pattern: require('sha1')($DATA) - - pattern: sha1($DATA) + - pattern: | + password: "admin" + - pattern: | + password: "password" + - pattern: | + password: "123456" + - pattern: | + password: "" + - pattern: | + { ..., user: "admin", password: "admin", ... } metadata: category: security - cwe: CWE-327 + owasp: "A05:2021" + cwe: CWE-798 confidence: high + subcategory: configuration + + # ===================================================================== + # A06:2021 - Vulnerable and Outdated Components + # ===================================================================== - # Insecure HTTP - - id: js-insecure-http-usage - message: "Use of HTTP instead of HTTPS detected" + # Deprecated APIs + - id: js-deprecated-crypto-api + message: "Deprecated crypto API - use crypto.createCipheriv instead" severity: MEDIUM languages: [javascript, typescript] - pattern-either: - - pattern: 'new URL("http://...")' - - pattern: 'fetch("http://...")' - - pattern: 'axios.get("http://...")' - - pattern: '"http://..."' + pattern: crypto.createCipher(...) metadata: category: security - cwe: CWE-319 - confidence: low + owasp: "A06:2021" + cwe: CWE-327 + confidence: high + subcategory: deprecated - # Regular expression DoS - - id: js-regex-dos - message: "Potential ReDoS (Regular Expression Denial of Service) vulnerability" + # Unsafe Buffer constructor + - id: js-unsafe-buffer + message: "Unsafe Buffer allocation - use Buffer.alloc() or Buffer.from()" severity: MEDIUM languages: [javascript, typescript] pattern-either: - - pattern: new RegExp($PATTERN + $USER_INPUT) - - pattern: $STR.match($PATTERN + $USER_INPUT) - - pattern: $STR.replace($PATTERN + $USER_INPUT, ...) + - pattern: new Buffer($SIZE) + - pattern: Buffer($SIZE) + - pattern: Buffer.allocUnsafe($SIZE) metadata: category: security - cwe: CWE-1333 - confidence: low + owasp: "A06:2021" + cwe: CWE-119 + confidence: high + subcategory: deprecated + + # ===================================================================== + # A07:2021 - Identification and Authentication Failures + # ===================================================================== - # DOM XSS sinks - - id: js-dom-xss-sinks - message: "Potential DOM XSS sink detected" + # Weak password requirements + - id: js-weak-password-validation + message: "Weak password validation - enforce strong password policy" severity: MEDIUM languages: [javascript, typescript] - pattern-either: - - pattern: $ELEMENT.setAttribute($ATTR, $USER_INPUT) - - pattern: $ELEMENT.src = $USER_INPUT - - pattern: $ELEMENT.href = $USER_INPUT - - pattern: location.href = $USER_INPUT - - pattern: window.location = $USER_INPUT + patterns: + - pattern-either: + - pattern: $PASSWORD.length < $N + - pattern: $PASSWORD.length > $MIN + - metavariable-comparison: + metavariable: $N + comparison: $N < 8 + - metavariable-comparison: + metavariable: $MIN + comparison: $MIN < 8 metadata: category: security - cwe: CWE-79 + owasp: "A07:2021" + cwe: CWE-521 confidence: low + subcategory: authentication # JWT without verification - id: js-jwt-no-verify - message: "JWT token used without proper verification" - severity: MEDIUM + message: "JWT decoded without signature verification - use jwt.verify()" + severity: HIGH languages: [javascript, typescript] pattern-either: - pattern: jwt.decode($TOKEN) - pattern: jsonwebtoken.decode($TOKEN) - - pattern: "jwt.verify($TOKEN, { verify: false })" + - pattern: | + jwt.verify($TOKEN, ..., { ..., verify: false, ... }) metadata: category: security + owasp: "A07:2021" cwe: CWE-347 + confidence: high + subcategory: authentication + + # Weak JWT secret + - id: js-weak-jwt-secret + message: "Weak JWT secret - use a strong random secret" + severity: HIGH + languages: [javascript, typescript] + patterns: + - pattern: jwt.sign(..., $SECRET, ...) + - metavariable-regex: + metavariable: $SECRET + regex: ^["'](secret|test|dev|password|123)["']$ + metadata: + category: security + owasp: "A07:2021" + cwe: CWE-798 + confidence: high + subcategory: authentication + + # Session fixation + - id: js-session-fixation + message: "Session fixation vulnerability - regenerate session after login" + severity: MEDIUM + languages: [javascript, typescript] + patterns: + - pattern-inside: | + $APP.post("/login", ..., async ($REQ, $RES) => { + ... + }) + - pattern-not-inside: | + ... + $REQ.session.regenerate(...) + ... + metadata: + category: security + owasp: "A07:2021" + cwe: CWE-384 + confidence: low + subcategory: authentication + + # ===================================================================== + # A08:2021 - Software and Data Integrity Failures + # ===================================================================== + + # Unsafe deserialization + - id: js-unsafe-deserialization + message: "Unsafe deserialization - can lead to remote code execution" + severity: CRITICAL + languages: [javascript, typescript] + pattern-either: + - pattern: JSON.parse($REQ.body) + - pattern: JSON.parse($REQ.query.$PARAM) + - pattern: eval($JSON_STR) + - pattern: Function("return " + $JSON_STR)() + - pattern: serialize.unserialize($DATA) + - pattern: node-serialize.unserialize($DATA) + metadata: + category: security + owasp: "A08:2021" + cwe: CWE-502 confidence: medium + subcategory: integrity - # === Low Severity Rules === + # Missing integrity check for external resources + - id: js-missing-sri + message: "External resource loaded without Subresource Integrity (SRI) check" + severity: MEDIUM + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: | + + - pattern: | + + - pattern: | + + - pattern-not: | + <... integrity="..." ...> + metadata: + category: security + owasp: "A08:2021" + cwe: CWE-353 + confidence: low + subcategory: integrity - # Console logging sensitive data - - id: js-console-log-sensitive - message: "Potentially sensitive data logged to console" - severity: LOW + # Insecure update mechanism + - id: js-insecure-auto-update + message: "Auto-update mechanism without integrity verification" + severity: HIGH + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: autoUpdater.checkForUpdates() + - pattern: autoUpdater.downloadUpdate() + - pattern-not-inside: | + ... + autoUpdater.on("update-downloaded", ..., (info) => { + ... + crypto.verify(...) + ... + }) + ... + metadata: + category: security + owasp: "A08:2021" + cwe: CWE-494 + confidence: low + subcategory: integrity + + # ===================================================================== + # A09:2021 - Security Logging and Monitoring Failures + # ===================================================================== + + # Sensitive data in logs + - id: js-sensitive-data-in-logs + message: "Sensitive data logged - can expose credentials or personal information" + severity: MEDIUM languages: [javascript, typescript] pattern-either: - - pattern: console.log(..., $VAR, ...) - - pattern: console.error(..., $VAR, ...) - - pattern: console.warn(..., $VAR, ...) - - pattern: console.info(..., $VAR, ...) - where: - - metavariable-regex: - metavariable: $VAR - regex: (?i).*(password|token|secret|key|credential).* + - pattern: console.log(..., $REQ.body.password, ...) + - pattern: console.log(..., $REQ.body.token, ...) + - pattern: console.log(..., $REQ.headers.authorization, ...) + - pattern: logger.info(..., $PASSWORD, ...) + - pattern: logger.debug(..., $TOKEN, ...) + - pattern: console.error(..., $SECRET, ...) metadata: category: security + owasp: "A09:2021" cwe: CWE-532 confidence: low + subcategory: logging - # Debugger statements - - id: js-debugger-statement - message: "Debugger statement found - should not be in production code" + # Missing error logging + - id: js-missing-error-logging + message: "Error caught but not logged - can hide security issues" severity: LOW languages: [javascript, typescript] - pattern: debugger + patterns: + - pattern: | + try { + ... + } catch ($ERR) { + } + - pattern-not-inside: | + try { + ... + } catch ($ERR) { + ... + console.error(...) + ... + } + - pattern-not-inside: | + try { + ... + } catch ($ERR) { + ... + logger.error(...) + ... + } metadata: category: security - cwe: CWE-489 + owasp: "A09:2021" + cwe: CWE-778 + confidence: low + subcategory: logging + + # ===================================================================== + # A10:2021 - Server-Side Request Forgery (SSRF) + # ===================================================================== + + # SSRF via user-controlled URL + - id: js-ssrf-vulnerability + message: "SSRF vulnerability - validate and whitelist URLs before making requests" + severity: HIGH + languages: [javascript, typescript] + pattern-either: + - pattern: fetch($REQ.query.$PARAM) + - pattern: fetch($REQ.body.$PARAM) + - pattern: axios.get($REQ.query.$PARAM) + - pattern: axios.post($REQ.body.$PARAM, ...) + - pattern: request($REQ.query.$PARAM) + - pattern: http.get($REQ.query.$PARAM) + - pattern: https.get($REQ.query.$PARAM) + - pattern: got($REQ.body.$PARAM) + metadata: + category: security + owasp: "A10:2021" + cwe: CWE-918 confidence: high + subcategory: ssrf + + # ===================================================================== + # JavaScript/TypeScript Best Practices + # ===================================================================== - # Alert/confirm/prompt usage - - id: js-browser-dialogs - message: "Browser dialog functions can be annoying and are often blocked" + # Unsafe type coercion + - id: js-unsafe-type-coercion + message: "Unsafe type coercion - use strict equality (===) instead" severity: LOW languages: [javascript, typescript] pattern-either: - - pattern: alert($MSG) - - pattern: confirm($MSG) - - pattern: prompt($MSG) + - pattern: $A == $B + - pattern: $A != $B metadata: - category: security - cwe: CWE-200 + category: best-practice + cwe: CWE-697 confidence: low + subcategory: type-safety - # Unvalidated redirects - - id: js-unvalidated-redirect - message: "Unvalidated redirect detected" + # Missing await on Promise + - id: js-missing-await + message: "Promise not awaited - may cause unexpected behavior" severity: LOW languages: [javascript, typescript] - pattern-either: - - pattern: res.redirect($USER_INPUT) - - pattern: response.redirect($USER_INPUT) - - pattern: window.location.href = $USER_INPUT - - pattern: document.location = $USER_INPUT + patterns: + - pattern-inside: | + async function $FUNC(...) { + ... + } + - pattern: $PROMISE + - metavariable-pattern: + metavariable: $PROMISE + patterns: + - pattern-either: + - pattern: fetch(...) + - pattern: $DB.query(...) + - pattern: $DB.execute(...) + - pattern-not: await $PROMISE metadata: - category: security - cwe: CWE-601 + category: best-practice + cwe: CWE-703 confidence: low + subcategory: async - # === Framework-specific Rules === + # Unhandled Promise rejection + - id: js-unhandled-promise-rejection + message: "Promise without error handling - can cause unhandled rejections" + severity: LOW + languages: [javascript, typescript] + patterns: + - pattern-either: + - pattern: | + $PROMISE.then(...) + - pattern: | + await $ASYNC_CALL + - pattern-not: | + $PROMISE.then(...).catch(...) + - pattern-not: | + try { + ... + await $ASYNC_CALL + ... + } catch (...) { + ... + } + metadata: + category: best-practice + cwe: CWE-755 + confidence: low + subcategory: error-handling - # Express.js security issues - - id: js-express-no-helmet - message: "Express app without helmet security middleware" + # RegEx Denial of Service (ReDoS) + - id: js-regex-dos + message: "Complex regex pattern - potential ReDoS vulnerability" severity: MEDIUM languages: [javascript, typescript] pattern-either: + - pattern: new RegExp($USER_INPUT) + - pattern: $STR.match($USER_INPUT) + - pattern: $STR.replace($USER_INPUT, ...) - pattern: | - const app = express() - ... + /(.+)+/ - pattern: | - var app = express() - ... - pattern-not-inside: - pattern: | - ... - app.use(helmet(...)) - ... + /(.*)+/ + - pattern: | + /([a-zA-Z]+)*/.test($INPUT) metadata: category: security - framework: express - cwe: CWE-200 + cwe: CWE-1333 + confidence: low + subcategory: dos - # React dangerous props + # Unsafe parseInt without radix + - id: js-parseint-missing-radix + message: "parseInt() without radix parameter - can cause unexpected results" + severity: LOW + languages: [javascript, typescript] + pattern: parseInt($STR) + metadata: + category: best-practice + cwe: CWE-704 + confidence: high + subcategory: type-safety + + # ===================================================================== + # Framework-Specific Rules + # ===================================================================== + + # React dangerouslySetInnerHTML - id: js-react-dangerous-html - message: "React dangerouslySetInnerHTML usage detected" + message: "React dangerouslySetInnerHTML can introduce XSS vulnerabilities" severity: HIGH - languages: [javascript, typescript, js, ts] - pattern: 'dangerouslySetInnerHTML: { __html: $HTML }' + languages: [javascript, typescript] + pattern: "dangerouslySetInnerHTML={{ __html: $HTML }}" metadata: category: security framework: react cwe: CWE-79 - confidence: medium + confidence: high + subcategory: xss + + # React missing key prop + - id: js-react-missing-key + message: "Missing key prop in list rendering - can cause rendering issues" + severity: LOW + languages: [javascript, typescript] + patterns: + - pattern: | + $ARR.map($ITEM => <$COMPONENT ... />) + - pattern-not: | + $ARR.map($ITEM => <$COMPONENT key={...} ... />) + metadata: + category: best-practice + framework: react + confidence: low + subcategory: performance - # Node.js specific - - id: js-node-buffer-alloc-unsafe - message: "Unsafe Buffer allocation detected" + # Express missing async error handler + - id: js-express-async-no-error-handler + message: "Async Express route handler without error handling" severity: MEDIUM languages: [javascript, typescript] + patterns: + - pattern: | + $APP.$METHOD($PATH, async ($REQ, $RES) => { + ... + }) + - pattern-not-inside: | + $APP.$METHOD($PATH, async ($REQ, $RES, $NEXT) => { + try { + ... + } catch ($ERR) { + ... + $NEXT($ERR) + ... + } + }) + metadata: + category: best-practice + framework: express + cwe: CWE-755 + confidence: low + subcategory: error-handling + + # Express trust proxy not set + - id: js-express-trust-proxy-not-set + message: "Express behind proxy without 'trust proxy' setting" + severity: LOW + languages: [javascript, typescript] + patterns: + - pattern: const $APP = express() + - pattern-not-inside: | + ... + $APP.set("trust proxy", ...) + ... + metadata: + category: configuration + framework: express + cwe: CWE-693 + confidence: low + subcategory: proxy + + # Next.js getServerSideProps without error handling + - id: js-nextjs-gsp-no-error-handling + message: "getServerSideProps without error handling" + severity: LOW + languages: [javascript, typescript] + patterns: + - pattern: | + export async function getServerSideProps(...) { + ... + } + - pattern-not-inside: | + export async function getServerSideProps(...) { + try { + ... + } catch (...) { + ... + } + } + metadata: + category: best-practice + framework: nextjs + cwe: CWE-755 + confidence: low + subcategory: error-handling + + # ===================================================================== + # Node.js Specific Vulnerabilities + # ===================================================================== + + # Unsafe file operations + - id: js-unsafe-file-operations + message: "Unsafe file operation - validate file paths" + severity: HIGH + languages: [javascript, typescript] pattern-either: - - pattern: new Buffer($SIZE) - - pattern: Buffer($SIZE) - - pattern: Buffer.allocUnsafe($SIZE) + - pattern: fs.unlinkSync($REQ.$PROP) + - pattern: fs.unlink($REQ.$PROP, ...) + - pattern: fs.rmdir($REQ.$PROP, ...) + - pattern: fs.rmdirSync($REQ.$PROP) + - pattern: fs.chmod($REQ.$PROP, ...) + - pattern: fs.chmodSync($REQ.$PROP, ...) metadata: category: security runtime: nodejs - cwe: CWE-119 + cwe: CWE-73 + confidence: high + subcategory: file-operations - # MongoDB injection - - id: js-mongodb-injection - message: "Potential MongoDB injection via object construction" + # Process execution with user input + - id: js-unsafe-process-spawn + message: "Unsafe process execution with user input" severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: $COLLECTION.find($USER_INPUT) - - pattern: $COLLECTION.findOne($USER_INPUT) - - pattern: $COLLECTION.update($USER_INPUT, ...) - - pattern: $COLLECTION.remove($USER_INPUT) - where: - - metavariable-pattern: - metavariable: $USER_INPUT - pattern: $OBJ + - pattern: spawn($REQ.$PROP, ...) + - pattern: spawnSync($REQ.$PROP, ...) + - pattern: fork($REQ.$PROP, ...) + - pattern: execFile($REQ.$PROP, ...) metadata: category: security - cwe: CWE-943 - confidence: low + runtime: nodejs + cwe: CWE-78 + confidence: high + subcategory: process - # LDAP injection - - id: js-ldap-injection - message: "Potential LDAP injection via string concatenation" - severity: HIGH + # Timing attack vulnerability + - id: js-timing-attack + message: "String comparison vulnerable to timing attacks - use crypto.timingSafeEqual()" + severity: MEDIUM languages: [javascript, typescript] - pattern-either: - - pattern: $CLIENT.search($FILTER + $USER_INPUT) - - pattern: $CLIENT.bind($DN + $USER_INPUT, ...) + patterns: + - pattern-either: + - pattern: $TOKEN === $USER_TOKEN + - pattern: $PASSWORD === $USER_PASSWORD + - pattern: $SECRET === $USER_SECRET + - metavariable-regex: + metavariable: $TOKEN + regex: (?i).*(token|secret|password|key).* metadata: category: security - cwe: CWE-90 - confidence: medium + cwe: CWE-208 + confidence: low + subcategory: crypto - # XXE (XML External Entity) - - id: js-xxe-vulnerability - message: "Potential XXE vulnerability in XML parsing" + # Unvalidated file upload + - id: js-unvalidated-file-upload + message: "File upload without validation - validate file type and size" severity: HIGH languages: [javascript, typescript] - pattern-either: - - pattern: new DOMParser().parseFromString($XML, "text/xml") - - pattern: libxmljs.parseXml($XML) - - pattern: xml2js.parseString($XML, ...) - pattern-not-inside: - pattern: | - ... - noent: false - ... + patterns: + - pattern: | + $APP.post($PATH, $UPLOAD.single(...), ...) + - pattern-not-inside: | + ... + if ($FILE.mimetype ...) { ... } + ... metadata: category: security - cwe: CWE-611 + cwe: CWE-434 confidence: low + subcategory: upload - # Weak session configuration - - id: js-weak-session-config - message: "Weak session configuration detected" + # Zip bomb / decompression bomb + - id: js-zip-bomb + message: "Zip decompression without size limit - vulnerable to zip bombs" severity: MEDIUM languages: [javascript, typescript] - pattern-either: - - pattern: | - session({ - ..., - secure: false, - ... - }) - - pattern: | - session({ - ..., - httpOnly: false, - ... - }) - - pattern: | - session({ - ..., - sameSite: false, - ... - }) + patterns: + - pattern-either: + - pattern: unzip.Extract(...) + - pattern: $ZIP.extractAllTo(...) + - pattern: decompress($FILE, ...) + - pattern-not-inside: | + ... + if ($SIZE > ...) { ... } + ... metadata: category: security - cwe: CWE-614 - confidence: medium \ No newline at end of file + cwe: CWE-409 + confidence: low + subcategory: dos \ No newline at end of file diff --git a/socket_basics/socket_basics.py b/socket_basics/socket_basics.py index 4a1c96f..10ff13d 100644 --- a/socket_basics/socket_basics.py +++ b/socket_basics/socket_basics.py @@ -297,13 +297,12 @@ def submit_socket_facts(self, socket_facts_path: Path, results: Dict[str, Any]) logger.debug(f"Full scan parameters: repo={repo_name}, branch={branch}, commit_hash={commit_hash}") logger.debug(f"Socket facts file path: {socket_facts_path}") - # Convert to absolute path to avoid SDK path parsing issues - absolute_socket_facts_path = socket_facts_path.absolute() - logger.debug(f"Absolute socket facts file path: {absolute_socket_facts_path}") + # Use just the filename without path for SDK fullscans.post + logger.debug(f"Socket facts file path: {socket_facts_path}") try: res = sdk.fullscans.post( - [str(absolute_socket_facts_path)], + [".socket.facts.json"], base_path=str(socket_facts_path.parent.absolute()), params=params, use_types=True, diff --git a/socket_basics/version.py b/socket_basics/version.py index bd538f7..66c607f 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.12" +__version__ = "1.0.13" From 180826d1a173f35ee6c8a47e838fc7008c5b5034 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 02:00:09 -0700 Subject: [PATCH 3/9] Updated actions yaml and parameters with the new options --- README.md | 10 +++--- action.yml | 10 ++++++ docs/github-action.md | 38 ++++++++++---------- docs/local-install-docker.md | 70 ++++++++++++++++++------------------ docs/parameters.md | 24 +++++++++++++ docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/version.py | 2 +- 8 files changed, 96 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 63a920c..c0a2d01 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.13 + uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.13 . +docker build -t socketdev/socket-basics:1.0.14 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.13 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.14 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/action.yml b/action.yml index d7667a4..eb3b2a1 100644 --- a/action.yml +++ b/action.yml @@ -12,6 +12,7 @@ runs: INPUT_ALL_LANGUAGES_ENABLED: ${{ inputs.all_languages_enabled }} INPUT_ALL_RULES_ENABLED: ${{ inputs.all_rules_enabled }} INPUT_CONTAINER_IMAGES_TO_SCAN: ${{ inputs.container_images }} + INPUT_CUSTOM_SAST_RULE_PATH: ${{ inputs.custom_sast_rule_path }} INPUT_CPP_DISABLED_RULES: ${{ inputs.cpp_disabled_rules }} INPUT_CPP_ENABLED_RULES: ${{ inputs.cpp_enabled_rules }} INPUT_CPP_SAST_ENABLED: ${{ inputs.cpp_sast_enabled }} @@ -81,6 +82,7 @@ runs: INPUT_TRUFFLEHOG_EXCLUDE_DIR: ${{ inputs.trufflehog_exclude_dir }} INPUT_TRUFFLEHOG_NOTIFICATION_METHOD: ${{ inputs.notification_method }} INPUT_TRUFFLEHOG_SHOW_UNVERIFIED: ${{ inputs.trufflehog_show_unverified }} + INPUT_USE_CUSTOM_SAST_RULES: ${{ inputs.use_custom_sast_rules }} INPUT_WEBHOOK_URL: ${{ inputs.webhook_url }} SOCKET_ADDITIONAL_PARAMS: ${{ inputs.socket_additional_params }} SOCKET_TIER_1_ENABLED: ${{ inputs.socket_tier_1_enabled }} @@ -126,6 +128,10 @@ inputs: description: "Comma-separated list of container images to scan (auto-enables image scanning)" required: false default: "" + custom_sast_rule_path: + description: "Relative path to custom SAST rules directory (relative to workspace if set, otherwise cwd)" + required: false + default: "custom_rules" cpp_disabled_rules: description: "Comma-separated list of C++ SAST rules to disable" required: false @@ -386,6 +392,10 @@ inputs: description: "Show unverified secrets in TruffleHog results" required: false default: "false" + use_custom_sast_rules: + description: "Use custom SAST rules instead of bundled rules (falls back to bundled rules for languages without custom rules)" + required: false + default: "false" webhook_url: description: "Generic webhook URL for WebhookNotifier" required: false diff --git a/docs/github-action.md b/docs/github-action.md index c90a864..1af49fa 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.13 + uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.13 +> - uses: SocketDev/socket-basics@1.0.14 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.13 +- uses: SocketDev/socket-basics@1.0.14 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.13 + uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.13 + uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.13:${{ github.sha }} . + run: docker build -t myapp:1.0.14:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.13 + uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.13 + uses: SocketDev/socket-basics@1.0.14 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.13 + - uses: SocketDev/socket-basics@1.0.14 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index d57d73c..f3f0f10 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.13 . +docker build -t socket-basics:1.0.14 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.13 . +docker build -t socket-basics:1.0.14 . # Or build with latest tag -docker build -t socket-basics:1.0.13:latest . +docker build -t socket-basics:1.0.14:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.13 . +docker build -t myorg/security-scanner:1.0.14 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.13 . +docker build --platform linux/amd64 -t socket-basics:1.0.14 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.13 socket-basics --version -docker run --rm socket-basics:1.0.13 socket --version -docker run --rm socket-basics:1.0.13 trivy --version -docker run --rm socket-basics:1.0.13 semgrep --version -docker run --rm socket-basics:1.0.13 trufflehog --version +docker run --rm socket-basics:1.0.14 socket-basics --version +docker run --rm socket-basics:1.0.14 socket --version +docker run --rm socket-basics:1.0.14 trivy --version +docker run --rm socket-basics:1.0.14 semgrep --version +docker run --rm socket-basics:1.0.14 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.13 + socket-basics:1.0.14 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.13').inside( + docker.image('socket-basics:1.0.14').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.13 + image: socket-basics:1.0.14 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.13 + socket-basics:1.0.14 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.13 + socket-basics:1.0.14 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.13 \ + socket-basics:1.0.14 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.13 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.14 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.13 .' +alias sb-build='docker build -t socket-basics:1.0.14 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.13" +IMAGE_NAME="socket-basics:1.0.14" ENV_FILE=".env" # Create results directory diff --git a/docs/parameters.md b/docs/parameters.md index 0a0105f..f2312db 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -182,6 +182,30 @@ Run all bundled SAST rules regardless of language filters. socket-basics --all-rules ``` +### `--use-custom-sast-rules` +Use custom SAST rules instead of bundled rules (falls back to bundled rules for languages without custom rules). + +**Environment Variable:** `INPUT_USE_CUSTOM_SAST_RULES` + +**Default:** `false` + +**Example:** +```bash +socket-basics --python --use-custom-sast-rules +``` + +### `--custom-sast-rule-path CUSTOM_SAST_RULE_PATH` +Relative path to custom SAST rules directory (relative to workspace if set, otherwise cwd). + +**Environment Variable:** `INPUT_CUSTOM_SAST_RULE_PATH` + +**Default:** `custom_rules` + +**Example:** +```bash +socket-basics --python --use-custom-sast-rules --custom-sast-rule-path "my_custom_rules" +``` + ### Language-Specific Rule Configuration For each language, you can enable or disable specific rules: diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 29ecdce..923b419 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.13 . +docker build -t socket-basics:1.0.14 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index 2a1c26a..2d6e31b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.13" +version = "1.0.14" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/version.py b/socket_basics/version.py index 66c607f..b19b12e 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.13" +__version__ = "1.0.14" From 6783ac5b080fa3f1215f17d2e0639192b6e213c6 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 02:25:51 -0700 Subject: [PATCH 4/9] Fixed the call to the Socket SDK for submitting the socket facts file --- README.md | 10 ++--- docs/github-action.md | 38 +++++++++--------- docs/local-install-docker.md | 70 +++++++++++++++++----------------- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/socket_basics.py | 18 ++++++--- socket_basics/version.py | 2 +- 7 files changed, 74 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index c0a2d01..5ce5c49 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.14 + uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.14 . +docker build -t socketdev/socket-basics:1.0.15 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.14 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.15 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index 1af49fa..dc8245a 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.14 + uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.14 +> - uses: SocketDev/socket-basics@1.0.15 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.14 +- uses: SocketDev/socket-basics@1.0.15 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.14 + uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.14 + uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.14:${{ github.sha }} . + run: docker build -t myapp:1.0.15:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.14 + uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.14 + uses: SocketDev/socket-basics@1.0.15 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.14 + - uses: SocketDev/socket-basics@1.0.15 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index f3f0f10..abbbcb5 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.14 . +docker build -t socket-basics:1.0.15 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.14 . +docker build -t socket-basics:1.0.15 . # Or build with latest tag -docker build -t socket-basics:1.0.14:latest . +docker build -t socket-basics:1.0.15:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.14 . +docker build -t myorg/security-scanner:1.0.15 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.14 . +docker build --platform linux/amd64 -t socket-basics:1.0.15 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.14 socket-basics --version -docker run --rm socket-basics:1.0.14 socket --version -docker run --rm socket-basics:1.0.14 trivy --version -docker run --rm socket-basics:1.0.14 semgrep --version -docker run --rm socket-basics:1.0.14 trufflehog --version +docker run --rm socket-basics:1.0.15 socket-basics --version +docker run --rm socket-basics:1.0.15 socket --version +docker run --rm socket-basics:1.0.15 trivy --version +docker run --rm socket-basics:1.0.15 semgrep --version +docker run --rm socket-basics:1.0.15 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.14 + socket-basics:1.0.15 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.14').inside( + docker.image('socket-basics:1.0.15').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.14 + image: socket-basics:1.0.15 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.14 + socket-basics:1.0.15 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.14 + socket-basics:1.0.15 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.14 \ + socket-basics:1.0.15 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.14 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.15 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.14 .' +alias sb-build='docker build -t socket-basics:1.0.15 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.14" +IMAGE_NAME="socket-basics:1.0.15" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 923b419..3debaee 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.14 . +docker build -t socket-basics:1.0.15 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index 2d6e31b..2207394 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.14" +version = "1.0.15" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/socket_basics.py b/socket_basics/socket_basics.py index 10ff13d..72214af 100644 --- a/socket_basics/socket_basics.py +++ b/socket_basics/socket_basics.py @@ -295,20 +295,26 @@ def submit_socket_facts(self, socket_facts_path: Path, results: Dict[str, Any]) # Submit the socket facts file logger.info(f"Submitting socket facts file to Socket API for organization: {socket_org}") logger.debug(f"Full scan parameters: repo={repo_name}, branch={branch}, commit_hash={commit_hash}") - logger.debug(f"Socket facts file path: {socket_facts_path}") - # Use just the filename without path for SDK fullscans.post - logger.debug(f"Socket facts file path: {socket_facts_path}") + # The SDK needs: + # 1. Absolute path to the file (so it can be opened) + # 2. base_path that the file path starts with (so it can be stripped for the upload key) + socket_facts_absolute = str(socket_facts_path.absolute()) + workspace_absolute = str(Path(self.config.workspace).absolute()) + + logger.debug(f"Socket facts absolute path: {socket_facts_absolute}") + logger.debug(f"Workspace absolute path: {workspace_absolute}") + logger.debug(f"File exists: {socket_facts_path.exists()}") + logger.debug(f"File starts with workspace: {socket_facts_absolute.startswith(workspace_absolute)}") try: res = sdk.fullscans.post( - [".socket.facts.json"], - base_path=str(socket_facts_path.parent.absolute()), + [socket_facts_absolute], params=params, use_types=True, use_lazy_loading=True, max_open_files=50, - base_paths=[str(self.config.workspace)] + base_path=workspace_absolute ) logger.debug(f"✓ SDK call completed") logger.debug(f"SDK response type: {type(res)}") diff --git a/socket_basics/version.py b/socket_basics/version.py index b19b12e..f871089 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.14" +__version__ = "1.0.15" From eb7c2d68f6dcb3fc6a3d585993120b9b5cb6d7cc Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 02:41:38 -0700 Subject: [PATCH 5/9] Updated default JS ruleset --- README.md | 10 +- docs/github-action.md | 38 +-- docs/local-install-docker.md | 70 ++-- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/connectors.yaml | 2 +- socket_basics/rules/javascript_typescript.yml | 307 +++++++++++++----- socket_basics/version.py | 2 +- 8 files changed, 289 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index 5ce5c49..18bfc9f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.15 + uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.15 . +docker build -t socketdev/socket-basics:1.0.16 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.15 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.16 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index dc8245a..c7c8cd7 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.15 + uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.15 +> - uses: SocketDev/socket-basics@1.0.16 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.15 +- uses: SocketDev/socket-basics@1.0.16 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.15 + uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.15 + uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.15:${{ github.sha }} . + run: docker build -t myapp:1.0.16:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.15 + uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.15 + uses: SocketDev/socket-basics@1.0.16 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.15 + - uses: SocketDev/socket-basics@1.0.16 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index abbbcb5..5b5f050 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.15 . +docker build -t socket-basics:1.0.16 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.15 . +docker build -t socket-basics:1.0.16 . # Or build with latest tag -docker build -t socket-basics:1.0.15:latest . +docker build -t socket-basics:1.0.16:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.15 . +docker build -t myorg/security-scanner:1.0.16 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.15 . +docker build --platform linux/amd64 -t socket-basics:1.0.16 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.15 socket-basics --version -docker run --rm socket-basics:1.0.15 socket --version -docker run --rm socket-basics:1.0.15 trivy --version -docker run --rm socket-basics:1.0.15 semgrep --version -docker run --rm socket-basics:1.0.15 trufflehog --version +docker run --rm socket-basics:1.0.16 socket-basics --version +docker run --rm socket-basics:1.0.16 socket --version +docker run --rm socket-basics:1.0.16 trivy --version +docker run --rm socket-basics:1.0.16 semgrep --version +docker run --rm socket-basics:1.0.16 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.15 + socket-basics:1.0.16 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.15').inside( + docker.image('socket-basics:1.0.16').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.15 + image: socket-basics:1.0.16 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.15 + socket-basics:1.0.16 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.15 + socket-basics:1.0.16 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.15 \ + socket-basics:1.0.16 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.15 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.16 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.15 .' +alias sb-build='docker build -t socket-basics:1.0.16 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.15" +IMAGE_NAME="socket-basics:1.0.16" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 3debaee..9140741 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.15 . +docker build -t socket-basics:1.0.16 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index 2207394..6d83491 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.15" +version = "1.0.16" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/connectors.yaml b/socket_basics/connectors.yaml index e2ffd47..bbb7202 100644 --- a/socket_basics/connectors.yaml +++ b/socket_basics/connectors.yaml @@ -184,7 +184,7 @@ connectors: description: "Comma-separated list of JavaScript/TypeScript SAST rules to enable (default: high-confidence rules)" env_variable: INPUT_JAVASCRIPT_ENABLED_RULES type: str - default: "js-code-injection-eval,js-sql-injection,js-nosql-injection,js-command-injection,js-ldap-injection,js-prototype-pollution,js-xss-innerhtml,js-dom-xss,js-path-traversal,js-open-redirect,js-cors-allow-all,js-weak-hash-md5,js-weak-hash-sha1,js-insecure-random,js-hardcoded-secret,js-weak-cipher,js-tls-reject-unauthorized-false,js-insecure-tls-version,js-jwt-no-verify,js-weak-jwt-secret,js-weak-session-cookie,js-default-credentials,js-error-stack-exposed,js-unsafe-deserialization,js-ssrf-vulnerability,js-react-dangerous-html,js-unsafe-buffer,js-unsafe-file-operations,js-unsafe-process-spawn,js-unvalidated-file-upload,js-debugger-statement,js-parseint-missing-radix" + default: "js-code-injection-eval,js-sql-injection,js-nosql-injection,js-command-injection,js-ldap-injection,js-prototype-pollution,js-xss-innerhtml,js-dom-xss,js-path-traversal,js-open-redirect,js-cors-allow-all,js-weak-hash-md5,js-weak-hash-sha1,js-hardcoded-secret,js-weak-cipher,js-tls-reject-unauthorized-false,js-insecure-tls-version,js-jwt-no-verify,js-weak-jwt-secret,js-weak-session-cookie,js-default-credentials,js-error-stack-exposed,js-unsafe-deserialization,js-ssrf-vulnerability,js-react-dangerous-html,js-unsafe-buffer,js-unsafe-file-operations,js-unsafe-process-spawn,js-debugger-statement,js-parseint-missing-radix" - name: javascript_disabled_rules option: --javascript-disabled-rules description: "Comma-separated list of JavaScript/TypeScript SAST rules to disable" diff --git a/socket_basics/rules/javascript_typescript.yml b/socket_basics/rules/javascript_typescript.yml index 60f8ddf..de01adf 100644 --- a/socket_basics/rules/javascript_typescript.yml +++ b/socket_basics/rules/javascript_typescript.yml @@ -42,15 +42,28 @@ rules: # Insecure direct object reference - id: js-idor-vulnerability - message: "Potential IDOR vulnerability - user input directly used to access resources" + message: "Potential IDOR vulnerability - verify user authorization before accessing resource" severity: HIGH languages: [javascript, typescript] - pattern-either: - - pattern: "$DB.find({ id: $REQ.params.id })" - - pattern: $DB.findById($REQ.params.id) - - pattern: "$DB.findOne({ _id: $REQ.params.id })" - - pattern: fs.readFile($REQ.params.file, ...) - - pattern: fs.readFileSync($REQ.params.file) + patterns: + - pattern-either: + - pattern: $DB.findById($REQ.params.id) + - pattern: "$DB.findOne({ _id: $REQ.params.id })" + - pattern: "$DB.findOne({ id: $REQ.params.id })" + - pattern: fs.readFile($REQ.params.file, ...) + - pattern: fs.readFileSync($REQ.params.file) + - pattern-not-inside: | + ... + if ($REQ.user.id === ...) { ... } + ... + - pattern-not-inside: | + ... + if ($RESOURCE.userId === $REQ.user.id) { ... } + ... + - pattern-not-inside: | + ... + authorize($REQ.user, ...) + ... metadata: category: security owasp: "A01:2021" @@ -64,6 +77,7 @@ rules: severity: HIGH languages: [javascript, typescript] pattern-either: + # File system operations with concatenated paths - pattern: fs.readFile($PATH + $USER_INPUT, ...) - pattern: fs.readFileSync($PATH + $USER_INPUT) - pattern: fs.writeFile($PATH + $USER_INPUT, ...) @@ -72,8 +86,39 @@ rules: - pattern: fs.createWriteStream($PATH + $USER_INPUT) - pattern: fs.readFile(`${$PATH}${$USER_INPUT}`, ...) - pattern: fs.readFileSync(`${$PATH}${$USER_INPUT}`) - - pattern: require($USER_INPUT) - - pattern: import($USER_INPUT) + - pattern: fs.writeFile(`${$PATH}${$USER_INPUT}`, ...) + - pattern: fs.writeFileSync(`${$PATH}${$USER_INPUT}`) + # User input directly in file operations (common with req.query/params/body) + - pattern: fs.readFile($REQ.query.$PARAM, ...) + - pattern: fs.readFileSync($REQ.query.$PARAM) + - pattern: fs.writeFile($REQ.query.$PARAM, ...) + - pattern: fs.writeFileSync($REQ.query.$PARAM) + - pattern: fs.readFile($REQ.params.$PARAM, ...) + - pattern: fs.readFileSync($REQ.params.$PARAM) + - pattern: fs.readFile($REQ.body.$PARAM, ...) + - pattern: fs.readFileSync($REQ.body.$PARAM) + - pattern: fs.createReadStream($REQ.query.$PARAM) + - pattern: fs.createReadStream($REQ.params.$PARAM) + - pattern: fs.createWriteStream($REQ.query.$PARAM) + - pattern: fs.createWriteStream($REQ.params.$PARAM) + # Path module with user input + - pattern: path.join($BASE, $REQ.query.$PARAM) + - pattern: path.join($BASE, $REQ.params.$PARAM) + - pattern: path.join($BASE, $REQ.body.$PARAM) + - pattern: path.resolve($BASE, $REQ.query.$PARAM) + - pattern: path.resolve($BASE, $REQ.params.$PARAM) + - pattern: path.resolve($BASE, $REQ.body.$PARAM) + # Dynamic require/import with request parameters (not static strings) + - pattern: require($REQ.query.$PARAM) + - pattern: require($REQ.params.$PARAM) + - pattern: require($REQ.body.$PARAM) + - pattern: import($REQ.query.$PARAM) + - pattern: import($REQ.params.$PARAM) + - pattern: import($REQ.body.$PARAM) + # Template literals with user input + - pattern: fs.readFile(`...${$REQ.query.$PARAM}...`, ...) + - pattern: fs.readFile(`...${$REQ.params.$PARAM}...`, ...) + - pattern: fs.readFile(`...${$REQ.body.$PARAM}...`, ...) metadata: category: security owasp: "A01:2021" @@ -87,18 +132,23 @@ rules: severity: MEDIUM languages: [javascript, typescript] pattern-either: + # Server-side redirects with user input - pattern: res.redirect($REQ.query.$PARAM) - pattern: res.redirect($REQ.params.$PARAM) - pattern: res.redirect($REQ.body.$PARAM) - - pattern: window.location = $USER_INPUT - - pattern: window.location.href = $USER_INPUT - - pattern: document.location = $USER_INPUT - - pattern: document.location.href = $USER_INPUT + # Client-side redirects with request data (more specific) + - pattern: window.location = $REQ.query.$PARAM + - pattern: window.location.href = $REQ.query.$PARAM + - pattern: document.location = $REQ.query.$PARAM + - pattern: document.location.href = $REQ.query.$PARAM + # URL concatenation with user input + - pattern: res.redirect($BASE + $REQ.query.$PARAM) + - pattern: res.redirect(`${$BASE}${$REQ.query.$PARAM}`) metadata: category: security owasp: "A01:2021" cwe: CWE-601 - confidence: medium + confidence: high subcategory: access-control # CORS misconfiguration @@ -159,15 +209,23 @@ rules: # Insecure random number generation - id: js-insecure-random - message: "Math.random() is not cryptographically secure - use crypto.randomBytes() instead" + message: "Math.random() used for security-sensitive operation - use crypto.randomBytes() instead" severity: HIGH languages: [javascript, typescript] - pattern: Math.random() + patterns: + - pattern: Math.random() + - pattern-inside: | + ... + $TOKEN = ... + ... + - metavariable-regex: + metavariable: $TOKEN + regex: (?i).*(token|secret|key|password|salt|nonce|session|auth|crypto).* metadata: category: security owasp: "A02:2021" cwe: CWE-338 - confidence: high + confidence: medium subcategory: crypto fix: "Use crypto.randomBytes() or crypto.getRandomValues() for security-sensitive operations" @@ -183,7 +241,10 @@ rules: - pattern: var $VAR = "..." - metavariable-regex: metavariable: $VAR - regex: (?i)(password|passwd|pwd|secret|token|api_key|apikey|private_key|access_token|auth_token|session_key|encryption_key) + regex: ^(password|passwd|pwd|secret|apiKey|api_key|privateKey|private_key|accessToken|access_token|authToken|auth_token|sessionKey|session_key)$ + - metavariable-comparison: + metavariable: $VAR + comparison: str($VAR).length > 8 metadata: category: security owasp: "A02:2021" @@ -260,18 +321,24 @@ rules: # Missing encryption in transit - id: js-insecure-protocol - message: "HTTP used instead of HTTPS - data transmitted in cleartext" + message: "HTTP server listening on external interface - should use HTTPS" severity: MEDIUM languages: [javascript, typescript] - pattern-either: - - pattern: require("http").createServer(...) - - pattern: http.createServer(...) - - pattern: | - fetch("http://...") - - pattern: | - axios.get("http://...") - - pattern: | - axios.post("http://...") + patterns: + - pattern-either: + - pattern: | + http.createServer(...).listen($PORT, "0.0.0.0", ...) + - pattern: | + http.createServer(...).listen($PORT) + - pattern: | + require("http").createServer(...).listen($PORT, "0.0.0.0", ...) + - pattern-not-inside: | + ... + if (process.env.NODE_ENV === "development") { ... } + ... + - metavariable-comparison: + metavariable: $PORT + comparison: $PORT != 3000 and $PORT != 8080 metadata: category: security owasp: "A02:2021" @@ -289,14 +356,25 @@ rules: severity: CRITICAL languages: [javascript, typescript] pattern-either: + # Direct eval usage - pattern: eval($EXPR) - pattern: eval($REQ.$PROP) - - pattern: Function($ARGS) - - pattern: new Function($ARGS) - - pattern: setTimeout($CODE_STR, ...) - - pattern: setInterval($CODE_STR, ...) - - pattern: vm.runInNewContext($CODE) - - pattern: vm.runInThisContext($CODE) + # Function constructor with user input + - pattern: Function($REQ.$PROP) + - pattern: new Function($REQ.$PROP) + # setTimeout/setInterval with string (not function) + - patterns: + - pattern-either: + - pattern: setTimeout($CODE_STR, ...) + - pattern: setInterval($CODE_STR, ...) + - metavariable-pattern: + metavariable: $CODE_STR + patterns: + - pattern-not: $FUNC + - pattern: "..." + # VM module with user input + - pattern: vm.runInNewContext($REQ.$PROP) + - pattern: vm.runInThisContext($REQ.$PROP) metadata: category: security owasp: "A03:2021" @@ -333,6 +411,7 @@ rules: severity: HIGH languages: [javascript, typescript] pattern-either: + # Directly passing request object to query methods - pattern: $COLLECTION.find($REQ.query) - pattern: $COLLECTION.find($REQ.body) - pattern: $COLLECTION.findOne($REQ.query) @@ -342,7 +421,11 @@ rules: - pattern: $COLLECTION.remove($REQ.query) - pattern: $COLLECTION.deleteOne($REQ.query) - pattern: $COLLECTION.deleteMany($REQ.query) - - pattern: "$MODEL.find({ ..., $FIELD: $REQ.query.$PARAM, ... })" + # Query operators with user input + - pattern: "$MODEL.find({ ..., $ne: $REQ.query.$PARAM, ... })" + - pattern: "$MODEL.find({ ..., $gt: $REQ.query.$PARAM, ... })" + - pattern: "$MODEL.find({ ..., $regex: $REQ.query.$PARAM, ... })" + - pattern: "$MODEL.find({ ..., $where: $REQ.query.$PARAM, ... })" metadata: category: security owasp: "A03:2021" @@ -390,41 +473,56 @@ rules: # XSS via innerHTML - id: js-xss-innerhtml - message: "XSS vulnerability via innerHTML - use textContent or sanitize input" + message: "XSS vulnerability via innerHTML with user input - use textContent or sanitize" severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: $ELEMENT.innerHTML = $VAR - - pattern: $ELEMENT.outerHTML = $VAR - - pattern: $ELEMENT.insertAdjacentHTML(..., $VAR) - - pattern: document.write($VAR) - - pattern: document.writeln($VAR) + # innerHTML with request data + - pattern: $ELEMENT.innerHTML = $REQ.query.$PARAM + - pattern: $ELEMENT.innerHTML = $REQ.body.$PARAM + - pattern: $ELEMENT.innerHTML = $REQ.params.$PARAM + - pattern: $ELEMENT.outerHTML = $REQ.query.$PARAM + - pattern: $ELEMENT.outerHTML = $REQ.body.$PARAM + # insertAdjacentHTML with request data + - pattern: $ELEMENT.insertAdjacentHTML(..., $REQ.query.$PARAM) + - pattern: $ELEMENT.insertAdjacentHTML(..., $REQ.body.$PARAM) + # document.write with request data + - pattern: document.write($REQ.query.$PARAM) + - pattern: document.writeln($REQ.body.$PARAM) + # Template literals with user input in innerHTML + - pattern: $ELEMENT.innerHTML = `...${$REQ.query.$PARAM}...` + - pattern: $ELEMENT.innerHTML = `...${$REQ.body.$PARAM}...` metadata: category: security owasp: "A03:2021" cwe: CWE-79 - confidence: medium + confidence: high subcategory: injection # DOM-based XSS - id: js-dom-xss - message: "DOM XSS vulnerability - validate and sanitize before using in DOM" + message: "DOM XSS vulnerability - validate and sanitize user input before using in DOM" severity: HIGH languages: [javascript, typescript] pattern-either: - - pattern: $ELEMENT.setAttribute("href", $USER_INPUT) - - pattern: $ELEMENT.setAttribute("src", $USER_INPUT) - - pattern: $ELEMENT.setAttribute("action", $USER_INPUT) - - pattern: $ELEMENT.setAttribute("formaction", $USER_INPUT) - - pattern: $ELEMENT.src = $USER_INPUT - - pattern: $ELEMENT.href = $USER_INPUT - - pattern: location = $USER_INPUT - - pattern: location.href = $USER_INPUT + # Setting dangerous attributes with request data + - pattern: $ELEMENT.setAttribute("href", $REQ.query.$PARAM) + - pattern: $ELEMENT.setAttribute("src", $REQ.query.$PARAM) + - pattern: $ELEMENT.setAttribute("action", $REQ.body.$PARAM) + - pattern: $ELEMENT.setAttribute("formaction", $REQ.body.$PARAM) + - pattern: $ELEMENT.src = $REQ.query.$PARAM + - pattern: $ELEMENT.href = $REQ.query.$PARAM + # Location manipulation with user input + - pattern: location = $REQ.query.$PARAM + - pattern: location.href = $REQ.query.$PARAM + - pattern: location.assign($REQ.query.$PARAM) + - pattern: window.location = $REQ.query.$PARAM + - pattern: window.location.href = $REQ.query.$PARAM metadata: category: security owasp: "A03:2021" cwe: CWE-79 - confidence: medium + confidence: high subcategory: injection # XXE (XML External Entity) @@ -455,18 +553,23 @@ rules: severity: HIGH languages: [javascript, typescript] pattern-either: + # Eval in template context - pattern: eval($TEMPLATE_STR) - - pattern: | - $TEMPLATE_ENGINE.render($TEMPLATE, { ..., userInput: $REQ.$PROP, ... }) - - pattern: | - _.template($USER_INPUT) - - pattern: | - Handlebars.compile($USER_INPUT) + # Lodash template with user input + - pattern: _.template($REQ.query.$PARAM) + - pattern: _.template($REQ.body.$PARAM) + - pattern: lodash.template($REQ.query.$PARAM) + # Handlebars compile with user input + - pattern: Handlebars.compile($REQ.body.$PARAM) + - pattern: Handlebars.compile($REQ.query.$PARAM) + # Template engines rendering user-controlled template strings + - pattern: $ENGINE.renderString($REQ.body.$PARAM, ...) + - pattern: pug.compile($REQ.body.$PARAM) metadata: category: security owasp: "A03:2021" cwe: CWE-1336 - confidence: medium + confidence: high subcategory: injection # Prototype pollution @@ -475,17 +578,28 @@ rules: severity: CRITICAL languages: [javascript, typescript] pattern-either: + # Direct prototype manipulation - pattern: $OBJ["__proto__"] = $VAL - pattern: $OBJ.__proto__ = $VAL - pattern: $OBJ["constructor"]["prototype"] = $VAL - pattern: $OBJ.constructor.prototype = $VAL - pattern: Object.setPrototypeOf($OBJ, $PROTO) - - pattern: $OBJ[$KEY] = $VAL + # Unsafe merge with user input + - pattern: Object.assign($TARGET, $REQ.body) + - pattern: Object.assign($TARGET, $REQ.query) + - pattern: lodash.merge($TARGET, $REQ.body) + - pattern: _.merge($TARGET, $REQ.query) + # Dynamic property assignment with __proto__ + - patterns: + - pattern: $OBJ[$KEY] = $VAL + - metavariable-regex: + metavariable: $KEY + regex: (__proto__|constructor|prototype) metadata: category: security owasp: "A03:2021" cwe: CWE-1321 - confidence: medium + confidence: high subcategory: injection # ===================================================================== @@ -803,17 +917,21 @@ rules: severity: CRITICAL languages: [javascript, typescript] pattern-either: - - pattern: JSON.parse($REQ.body) - - pattern: JSON.parse($REQ.query.$PARAM) - - pattern: eval($JSON_STR) - - pattern: Function("return " + $JSON_STR)() + # Dangerous deserialization libraries - pattern: serialize.unserialize($DATA) - pattern: node-serialize.unserialize($DATA) + - pattern: funcster.deepDeserialize($DATA) + # Eval-based JSON parsing + - pattern: eval("(" + $JSON_STR + ")") + - pattern: Function("return " + $JSON_STR)() + # VM module with untrusted data + - pattern: vm.runInNewContext($REQ.body.$PARAM) + - pattern: vm.runInThisContext($REQ.query.$PARAM) metadata: category: security owasp: "A08:2021" cwe: CWE-502 - confidence: medium + confidence: high subcategory: integrity # Missing integrity check for external resources @@ -1020,19 +1138,27 @@ rules: severity: MEDIUM languages: [javascript, typescript] pattern-either: - - pattern: new RegExp($USER_INPUT) - - pattern: $STR.match($USER_INPUT) - - pattern: $STR.replace($USER_INPUT, ...) + # User input used as regex + - pattern: new RegExp($REQ.query.$PARAM) + - pattern: new RegExp($REQ.body.$PARAM) + - pattern: RegExp($REQ.query.$PARAM) + # Dangerous regex patterns (nested quantifiers) - pattern: | /(.+)+/ - pattern: | /(.*)+/ - pattern: | - /([a-zA-Z]+)*/.test($INPUT) + /(.*)*/ + - pattern: | + /([a-zA-Z]+)*/ + - pattern: | + /(a+)+/ + - pattern: | + /(a|a)*/ metadata: category: security cwe: CWE-1333 - confidence: low + confidence: medium subcategory: dos # Unsafe parseInt without radix @@ -1082,7 +1208,7 @@ rules: # Express missing async error handler - id: js-express-async-no-error-handler - message: "Async Express route handler without error handling" + message: "Async Express route handler without try-catch - errors won't be caught" severity: MEDIUM languages: [javascript, typescript] patterns: @@ -1091,12 +1217,18 @@ rules: ... }) - pattern-not-inside: | - $APP.$METHOD($PATH, async ($REQ, $RES, $NEXT) => { + $APP.$METHOD($PATH, async ($REQ, $RES) => { try { ... } catch ($ERR) { ... - $NEXT($ERR) + } + }) + - pattern-not-inside: | + $APP.$METHOD($PATH, async ($REQ, $RES, $NEXT) => { + try { + ... + } catch ($ERR) { ... } }) @@ -1104,7 +1236,7 @@ rules: category: best-practice framework: express cwe: CWE-755 - confidence: low + confidence: medium subcategory: error-handling # Express trust proxy not set @@ -1197,12 +1329,25 @@ rules: languages: [javascript, typescript] patterns: - pattern-either: - - pattern: $TOKEN === $USER_TOKEN - - pattern: $PASSWORD === $USER_PASSWORD - - pattern: $SECRET === $USER_SECRET - - metavariable-regex: - metavariable: $TOKEN - regex: (?i).*(token|secret|password|key).* + # Direct comparison of sensitive values + - patterns: + - pattern: $A === $B + - metavariable-regex: + metavariable: $A + regex: .*(token|Token|TOKEN|secret|Secret|SECRET|key|Key|KEY).* + - metavariable-regex: + metavariable: $B + regex: .*(req|REQ|request|input|user|User).* + # Password comparisons + - patterns: + - pattern: $PASSWORD === $INPUT_PASSWORD + - metavariable-regex: + metavariable: $PASSWORD + regex: .*(password|Password|PASSWORD|passwd).* + - pattern-not-inside: | + ... + crypto.timingSafeEqual(...) + ... metadata: category: security cwe: CWE-208 diff --git a/socket_basics/version.py b/socket_basics/version.py index f871089..13361d1 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.15" +__version__ = "1.0.16" From 8cc913b187c6aa4ce2ee508f26951bf8c28fd074 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 02:58:49 -0700 Subject: [PATCH 6/9] Fix exclude logic --- README.md | 10 +-- docs/github-action.md | 38 +++++----- docs/local-install-docker.md | 70 +++++++++---------- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/core/connector/normalizer.py | 29 ++++++++ .../core/connector/opengrep/__init__.py | 8 +++ socket_basics/version.py | 2 +- 8 files changed, 99 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 18bfc9f..9bce0d7 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.16 + uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.16 . +docker build -t socketdev/socket-basics:1.0.17 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.16 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.17 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index c7c8cd7..5527817 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.16 + uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.16 +> - uses: SocketDev/socket-basics@1.0.17 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.16 +- uses: SocketDev/socket-basics@1.0.17 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.16 + uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.16 + uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.16:${{ github.sha }} . + run: docker build -t myapp:1.0.17:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.16 + uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.16 + uses: SocketDev/socket-basics@1.0.17 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.16 + - uses: SocketDev/socket-basics@1.0.17 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 5b5f050..f0362c4 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.16 . +docker build -t socket-basics:1.0.17 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.16 . +docker build -t socket-basics:1.0.17 . # Or build with latest tag -docker build -t socket-basics:1.0.16:latest . +docker build -t socket-basics:1.0.17:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.16 . +docker build -t myorg/security-scanner:1.0.17 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.16 . +docker build --platform linux/amd64 -t socket-basics:1.0.17 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.16 socket-basics --version -docker run --rm socket-basics:1.0.16 socket --version -docker run --rm socket-basics:1.0.16 trivy --version -docker run --rm socket-basics:1.0.16 semgrep --version -docker run --rm socket-basics:1.0.16 trufflehog --version +docker run --rm socket-basics:1.0.17 socket-basics --version +docker run --rm socket-basics:1.0.17 socket --version +docker run --rm socket-basics:1.0.17 trivy --version +docker run --rm socket-basics:1.0.17 semgrep --version +docker run --rm socket-basics:1.0.17 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.16 + socket-basics:1.0.17 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.16').inside( + docker.image('socket-basics:1.0.17').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.16 + image: socket-basics:1.0.17 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.16 + socket-basics:1.0.17 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.16 + socket-basics:1.0.17 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.16 \ + socket-basics:1.0.17 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.16 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.17 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.16 .' +alias sb-build='docker build -t socket-basics:1.0.17 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.16" +IMAGE_NAME="socket-basics:1.0.17" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 9140741..c569381 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.16 . +docker build -t socket-basics:1.0.17 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index 6d83491..afde3b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.16" +version = "1.0.17" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/core/connector/normalizer.py b/socket_basics/core/connector/normalizer.py index 783ecdc..8837aa2 100644 --- a/socket_basics/core/connector/normalizer.py +++ b/socket_basics/core/connector/normalizer.py @@ -38,6 +38,35 @@ def _normalize_alert(a: Dict[str, Any], connector: Any | None = None, default_ge a['severity'] = a['severity'].lower() # Minimal normalization: lowercase severity and ensure action exists + # Check if this alert's rule is in the disabled rules list for any language + # If so, set action to 'ignore' regardless of severity + try: + if connector and hasattr(connector, 'config'): + rule_id = a.get('title') or a.get('ruleId') or a.get('props', {}).get('ruleId') + if rule_id: + # Check all language disabled_rules configs + disabled_rule_params = [ + 'python_disabled_rules', 'javascript_disabled_rules', 'go_disabled_rules', + 'java_disabled_rules', 'kotlin_disabled_rules', 'scala_disabled_rules', + 'php_disabled_rules', 'ruby_disabled_rules', 'csharp_disabled_rules', + 'dotnet_disabled_rules', 'c_disabled_rules', 'cpp_disabled_rules', + 'swift_disabled_rules', 'rust_disabled_rules', 'elixir_disabled_rules', + 'erlang_disabled_rules', 'trivy_disabled_rules' + ] + for param in disabled_rule_params: + try: + disabled_rules_str = connector.config.get(param, '') + if disabled_rules_str: + disabled_rules = [r.strip() for r in disabled_rules_str.split(',') if r.strip()] + if rule_id in disabled_rules: + logger.debug(f"Rule {rule_id} is disabled via {param}, setting action to 'ignore'") + a['action'] = 'ignore' + return a + except Exception: + pass + except Exception: + logger.debug('Failed to check disabled rules for alert', exc_info=True) + # Ensure action is one of allowed values; derive from severity when missing/invalid try: allowed_actions = ('error', 'warn', 'monitor', 'ignore') diff --git a/socket_basics/core/connector/opengrep/__init__.py b/socket_basics/core/connector/opengrep/__init__.py index e0a4bd0..d6e8c1f 100644 --- a/socket_basics/core/connector/opengrep/__init__.py +++ b/socket_basics/core/connector/opengrep/__init__.py @@ -395,6 +395,14 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: "internal": True, 'alerts': [] } + + # Normalize alert action based on disabled rules before adding to component + from ..normalizer import _normalize_alert + try: + alert = _normalize_alert(alert, connector=self) + except Exception: + logger.debug('Failed to normalize alert action', exc_info=True) + comps[comp_id]['alerts'].append(alert) except Exception: logger.debug('Failed to convert single opengrep result to alert', exc_info=True) diff --git a/socket_basics/version.py b/socket_basics/version.py index 13361d1..8510098 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.16" +__version__ = "1.0.17" From 0913ff7b349f68eebc4a6e41186f56b412a0b897 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 09:37:46 -0700 Subject: [PATCH 7/9] Added the sast custom rules folder to default exclusion if used --- README.md | 10 +-- docs/github-action.md | 38 +++++----- docs/local-install-docker.md | 70 +++++++++---------- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- socket_basics/core/config.py | 2 + .../core/connector/opengrep/__init__.py | 3 + socket_basics/version.py | 2 +- 8 files changed, 67 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 9bce0d7..d4ee384 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.17 + uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.17 . +docker build -t socketdev/socket-basics:1.0.18 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.17 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.18 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index 5527817..b236f0a 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.17 + uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.17 +> - uses: SocketDev/socket-basics@1.0.18 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.17 +- uses: SocketDev/socket-basics@1.0.18 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.17 + uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.17 + uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.17:${{ github.sha }} . + run: docker build -t myapp:1.0.18:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.17 + uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.17 + uses: SocketDev/socket-basics@1.0.18 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.17 + - uses: SocketDev/socket-basics@1.0.18 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index f0362c4..967640c 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.17 . +docker build -t socket-basics:1.0.18 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.17 . +docker build -t socket-basics:1.0.18 . # Or build with latest tag -docker build -t socket-basics:1.0.17:latest . +docker build -t socket-basics:1.0.18:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.17 . +docker build -t myorg/security-scanner:1.0.18 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.17 . +docker build --platform linux/amd64 -t socket-basics:1.0.18 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.17 socket-basics --version -docker run --rm socket-basics:1.0.17 socket --version -docker run --rm socket-basics:1.0.17 trivy --version -docker run --rm socket-basics:1.0.17 semgrep --version -docker run --rm socket-basics:1.0.17 trufflehog --version +docker run --rm socket-basics:1.0.18 socket-basics --version +docker run --rm socket-basics:1.0.18 socket --version +docker run --rm socket-basics:1.0.18 trivy --version +docker run --rm socket-basics:1.0.18 semgrep --version +docker run --rm socket-basics:1.0.18 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.17 + socket-basics:1.0.18 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.17').inside( + docker.image('socket-basics:1.0.18').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.17 + image: socket-basics:1.0.18 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.17 + socket-basics:1.0.18 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.17 + socket-basics:1.0.18 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.17 \ + socket-basics:1.0.18 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.17 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.18 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.17 .' +alias sb-build='docker build -t socket-basics:1.0.18 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.17" +IMAGE_NAME="socket-basics:1.0.18" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index c569381..a6c8678 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.17 . +docker build -t socket-basics:1.0.18 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index afde3b8..43fde25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.17" +version = "1.0.18" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/core/config.py b/socket_basics/core/config.py index b2beed6..87f256a 100644 --- a/socket_basics/core/config.py +++ b/socket_basics/core/config.py @@ -1469,6 +1469,8 @@ def discover_all_files(workspace_path: str, respect_gitignore: bool = True) -> L 'node_modules/**', '.tmp', '.tmp/**', + 'custom_rules', + 'custom_rules/**', ] all_patterns = gitignore_patterns + default_ignore_patterns diff --git a/socket_basics/core/connector/opengrep/__init__.py b/socket_basics/core/connector/opengrep/__init__.py index d6e8c1f..41c14ae 100644 --- a/socket_basics/core/connector/opengrep/__init__.py +++ b/socket_basics/core/connector/opengrep/__init__.py @@ -140,6 +140,9 @@ def scan(self) -> Dict[str, Any]: if not config_args and self.config.get('all_languages_enabled', False): try: for p in Path(rules_dir).glob('*.yml'): + # Skip tests.yml from community rules + if p.name == 'tests.yml': + continue config_args.extend(['--config', str(p)]) except Exception: pass diff --git a/socket_basics/version.py b/socket_basics/version.py index 8510098..441304c 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.17" +__version__ = "1.0.18" From 563aaa1d6fcf1a333121d951815747321a6629d4 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 10:17:58 -0700 Subject: [PATCH 8/9] Added exclusions for *.test.yml and *.test.yaml for sast custom rules --- README.md | 10 +-- docs/github-action.md | 38 +++++----- docs/local-install-docker.md | 70 +++++++++--------- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- .../core/connector/opengrep/__init__.py | 72 +++++++++---------- .../core/connector/opengrep/custom_rules.py | 4 ++ socket_basics/version.py | 2 +- 8 files changed, 102 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index d4ee384..337f28d 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.18 + uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.18 . +docker build -t socketdev/socket-basics:1.0.19 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.18 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.19 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/docs/github-action.md b/docs/github-action.md index b236f0a..d82a5ca 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.18 + uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.18 +> - uses: SocketDev/socket-basics@1.0.19 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.18 +- uses: SocketDev/socket-basics@1.0.19 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.18 + uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.18 + uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.18:${{ github.sha }} . + run: docker build -t myapp:1.0.19:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.18 + uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.18 + uses: SocketDev/socket-basics@1.0.19 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.18 + - uses: SocketDev/socket-basics@1.0.19 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 967640c..db12eba 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.18 . +docker build -t socket-basics:1.0.19 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.18 . +docker build -t socket-basics:1.0.19 . # Or build with latest tag -docker build -t socket-basics:1.0.18:latest . +docker build -t socket-basics:1.0.19:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.18 . +docker build -t myorg/security-scanner:1.0.19 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.18 . +docker build --platform linux/amd64 -t socket-basics:1.0.19 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.18 socket-basics --version -docker run --rm socket-basics:1.0.18 socket --version -docker run --rm socket-basics:1.0.18 trivy --version -docker run --rm socket-basics:1.0.18 semgrep --version -docker run --rm socket-basics:1.0.18 trufflehog --version +docker run --rm socket-basics:1.0.19 socket-basics --version +docker run --rm socket-basics:1.0.19 socket --version +docker run --rm socket-basics:1.0.19 trivy --version +docker run --rm socket-basics:1.0.19 semgrep --version +docker run --rm socket-basics:1.0.19 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.18 + socket-basics:1.0.19 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.18').inside( + docker.image('socket-basics:1.0.19').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.18 + image: socket-basics:1.0.19 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.18 + socket-basics:1.0.19 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.18 + socket-basics:1.0.19 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.18 \ + socket-basics:1.0.19 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.18 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.19 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.18 .' +alias sb-build='docker build -t socket-basics:1.0.19 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.18" +IMAGE_NAME="socket-basics:1.0.19" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index a6c8678..6971282 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.18 . +docker build -t socket-basics:1.0.19 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index 43fde25..b8e16c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.18" +version = "1.0.19" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/core/connector/opengrep/__init__.py b/socket_basics/core/connector/opengrep/__init__.py index 41c14ae..264d657 100644 --- a/socket_basics/core/connector/opengrep/__init__.py +++ b/socket_basics/core/connector/opengrep/__init__.py @@ -265,6 +265,36 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: for r in results: try: path = r.get('path') or (r.get('extra', {}) or {}).get('file') or 'unknown' + + # Normalize path early to strip workspace/temp/custom_rules paths + normalized_path = path + try: + from pathlib import Path as _P + p = _P(path) + ws = getattr(self.config, 'workspace', None) + ws_root = getattr(ws, 'path', None) or getattr(ws, 'root', None) or ws + if ws_root: + # If path is absolute and inside workspace, make it relative + if p.is_absolute(): + try: + if str(p).startswith(str(ws_root)): + p = _P(os.path.relpath(str(p), str(ws_root))) + except Exception: + pass + else: + # Remove leading workspace folder components + parts = str(p).split(os.sep) + ws_name = os.path.basename(str(ws_root)) + if parts and (parts[0] == ws_name or (len(parts) >= 2 and parts[0] in ('.', '..') and parts[1] == ws_name)): + if parts[0] == ws_name: + parts = parts[1:] + else: + parts = parts[2:] + p = _P(os.path.join(*parts)) if parts else _P('') + normalized_path = str(p.as_posix()) + except Exception: + pass + # Preserve original identifier so we can annotate generatedBy when # the rule comes from the bundled socket_basics ruleset original_check_id = r.get('check_id') or (r.get('extra') or {}).get('rule_id') or '' @@ -309,7 +339,7 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: 'confidence': (r.get('extra') or {}).get('metadata', {}).get('confidence', ''), 'fingerprint': (r.get('extra') or {}).get('fingerprint') or '', # Fill commonly-consumed fields so notifiers can format Location/Lines - 'filePath': path, + 'filePath': normalized_path, 'startLine': start, 'endLine': end, 'codeSnippet': (r.get('extra') or {}).get('lines') or (r.get('extra') or {}).get('snippet') or '' @@ -321,7 +351,7 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: detected_subtype = None try: from pathlib import Path as _P - ext = (_P(path).suffix or '').lower() + ext = (_P(normalized_path).suffix or '').lower() if ext == '.py' or (isinstance(check_id, str) and check_id.startswith('python-')): detected_subtype = 'sast-python' elif ext in ('.js', '.ts') or (isinstance(check_id, str) and check_id.startswith('js-')): @@ -352,49 +382,19 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: else: alert.setdefault('subType', 'sast-generic') - # Normalize path and strip workspace prefix if present so component - # names are stable and do not include the workspace folder. + # Build component ID from normalized path try: - from pathlib import Path as _P import hashlib as _hash - p = _P(path) - # Resolve relative to workspace when present so paths are stable - try: - ws = getattr(self.config, 'workspace', None) - ws_root = getattr(ws, 'path', None) or getattr(ws, 'root', None) or ws - if ws_root: - # If path is absolute and inside workspace, make it relative - if p.is_absolute(): - try: - if str(p).startswith(str(ws_root)): - p = _P(os.path.relpath(str(p), str(ws_root))) - except Exception: - pass - else: - # Remove leading workspace folder components like "../NodeGoat" or "NodeGoat" - parts = str(p).split(os.sep) - ws_name = os.path.basename(str(ws_root)) - if parts and (parts[0] == ws_name or (len(parts) >= 2 and parts[0] in ('.', '..') and parts[1] == ws_name)): - # find index after workspace name - if parts[0] == ws_name: - parts = parts[1:] - else: - parts = parts[2:] - p = _P(os.path.join(*parts)) if parts else _P('') - except Exception: - pass - # Build a normalized identifier from path and filename - norm = str(p.as_posix()) - comp_id = _hash.sha256(norm.encode('utf-8')).hexdigest() + comp_id = _hash.sha256(normalized_path.encode('utf-8')).hexdigest() except Exception: - comp_id = path + comp_id = normalized_path if comp_id not in comps: comps[comp_id] = { 'id': comp_id, 'type': 'generic', 'subPath': detected_subtype, - 'name': path, + 'name': normalized_path, "internal": True, 'alerts': [] } diff --git a/socket_basics/core/connector/opengrep/custom_rules.py b/socket_basics/core/connector/opengrep/custom_rules.py index 9a5ce71..a13fe3f 100644 --- a/socket_basics/core/connector/opengrep/custom_rules.py +++ b/socket_basics/core/connector/opengrep/custom_rules.py @@ -86,6 +86,10 @@ def _collect_rules_by_file(self, enabled_languages: List[str]) -> Dict[str, List # Find all YAML files recursively yaml_files = list(self.custom_rules_path.rglob('*.yml')) + list(self.custom_rules_path.rglob('*.yaml')) + + # Filter out test files + yaml_files = [f for f in yaml_files if not (f.name.endswith('.test.yml') or f.name.endswith('.test.yaml'))] + logger.info(f"Found {len(yaml_files)} custom rule files in {self.custom_rules_path}") for yaml_file in yaml_files: diff --git a/socket_basics/version.py b/socket_basics/version.py index 441304c..b931c6a 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.18" +__version__ = "1.0.19" From 9bc90f90468c8be4ce30a7abe6fa56636bde6c15 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Fri, 24 Oct 2025 11:08:59 -0700 Subject: [PATCH 9/9] more fixes for excluding the custom rules folder --- README.md | 10 +-- action.yml | 5 ++ docs/github-action.md | 38 +++++----- docs/local-install-docker.md | 70 +++++++++---------- docs/pre-commit-hook.md | 2 +- pyproject.toml | 2 +- .../core/connector/opengrep/__init__.py | 56 ++++++++++++++- socket_basics/version.py | 2 +- 8 files changed, 121 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 337f28d..832f931 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.19 + uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -112,7 +112,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -123,7 +123,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -139,10 +139,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.19 . +docker build -t socketdev/socket-basics:1.0.20 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.19 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.20 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ diff --git a/action.yml b/action.yml index eb3b2a1..1c15b6f 100644 --- a/action.yml +++ b/action.yml @@ -8,6 +8,7 @@ runs: env: # Core GitHub variables (these are automatically available, but we explicitly pass GITHUB_TOKEN) GITHUB_TOKEN: ${{ inputs.github_token }} + INPUT_WORKSPACE: ${{ inputs.workspace }} # Input mappings for all parameters INPUT_ALL_LANGUAGES_ENABLED: ${{ inputs.all_languages_enabled }} INPUT_ALL_RULES_ENABLED: ${{ inputs.all_rules_enabled }} @@ -88,6 +89,10 @@ runs: SOCKET_TIER_1_ENABLED: ${{ inputs.socket_tier_1_enabled }} inputs: + workspace: + description: "Workspace directory to scan (defaults to GITHUB_WORKSPACE)" + required: false + default: "" socket_org: description: "Socket organization slug (required for Enterprise features)" required: false diff --git a/docs/github-action.md b/docs/github-action.md index d82a5ca..7ef8a04 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.19 + uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -78,7 +78,7 @@ Include these in your workflow's `jobs..permissions` section. **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -92,7 +92,7 @@ Include these in your workflow's `jobs..permissions` section. **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -104,7 +104,7 @@ Include these in your workflow's `jobs..permissions` section. **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -115,7 +115,7 @@ Include these in your workflow's `jobs..permissions` section. **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -124,7 +124,7 @@ Include these in your workflow's `jobs..permissions` section. ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -154,7 +154,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -166,7 +166,7 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev > **Note:** You can also pass credentials using environment variables instead of the `with:` section: > ```yaml -> - uses: SocketDev/socket-basics@1.0.19 +> - uses: SocketDev/socket-basics@1.0.20 > env: > SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} > with: @@ -184,7 +184,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -196,7 +196,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -211,7 +211,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -223,7 +223,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -235,7 +235,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@1.0.19 +- uses: SocketDev/socket-basics@1.0.20 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -271,7 +271,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.19 + uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -317,7 +317,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Full Security Scan - uses: SocketDev/socket-basics@1.0.19 + uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -368,10 +368,10 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build Docker Image - run: docker build -t myapp:1.0.19:${{ github.sha }} . + run: docker build -t myapp:1.0.20:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@1.0.19 + uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -404,7 +404,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run Socket Basics - uses: SocketDev/socket-basics@1.0.19 + uses: SocketDev/socket-basics@1.0.20 env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: @@ -497,7 +497,7 @@ env: ```yaml steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - Must be first - - uses: SocketDev/socket-basics@1.0.19 + - uses: SocketDev/socket-basics@1.0.20 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index db12eba..2362023 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.19 . +docker build -t socket-basics:1.0.20 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.19 . +docker build -t socket-basics:1.0.20 . # Or build with latest tag -docker build -t socket-basics:1.0.19:latest . +docker build -t socket-basics:1.0.20:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.19 . +docker build -t myorg/security-scanner:1.0.20 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.19 . +docker build --platform linux/amd64 -t socket-basics:1.0.20 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.19 socket-basics --version -docker run --rm socket-basics:1.0.19 socket --version -docker run --rm socket-basics:1.0.19 trivy --version -docker run --rm socket-basics:1.0.19 semgrep --version -docker run --rm socket-basics:1.0.19 trufflehog --version +docker run --rm socket-basics:1.0.20 socket-basics --version +docker run --rm socket-basics:1.0.20 socket --version +docker run --rm socket-basics:1.0.20 trivy --version +docker run --rm socket-basics:1.0.20 semgrep --version +docker run --rm socket-basics:1.0.20 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.19 + socket-basics:1.0.20 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.19').inside( + docker.image('socket-basics:1.0.20').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.19 + image: socket-basics:1.0.20 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.19 + socket-basics:1.0.20 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.19 + socket-basics:1.0.20 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.19 \ + socket-basics:1.0.20 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.19 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.20 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.19 .' +alias sb-build='docker build -t socket-basics:1.0.20 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.19" +IMAGE_NAME="socket-basics:1.0.20" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 6971282..660c64b 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.19 . +docker build -t socket-basics:1.0.20 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index b8e16c9..ac8a699 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.19" +version = "1.0.20" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/core/connector/opengrep/__init__.py b/socket_basics/core/connector/opengrep/__init__.py index 264d657..84edeba 100644 --- a/socket_basics/core/connector/opengrep/__init__.py +++ b/socket_basics/core/connector/opengrep/__init__.py @@ -266,6 +266,43 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: try: path = r.get('path') or (r.get('extra', {}) or {}).get('file') or 'unknown' + # Skip files from custom_rules directory - these are rule files, not source code + # Check if path starts with custom_rules (relative to workspace/cwd) + try: + from pathlib import Path as _P + p = _P(path) + # Get custom rules path from config + custom_rules_path = self.config.get_custom_rules_path() + if custom_rules_path: + custom_rules_path = Path(custom_rules_path) + # Check if the file path is inside the custom rules directory + try: + # For absolute paths + if p.is_absolute() and custom_rules_path.is_absolute(): + try: + p.relative_to(custom_rules_path) + logger.debug(f"Skipping result from custom_rules directory: {path}") + continue + except ValueError: + pass + # For relative paths, check if path starts with custom_rules + else: + path_str = str(p.as_posix()) + custom_rules_str = str(custom_rules_path.as_posix()) + # Normalize both to relative paths + if path_str.startswith(custom_rules_str + '/') or path_str == custom_rules_str: + logger.debug(f"Skipping result from custom_rules directory: {path}") + continue + # Also check if just the first component matches (e.g., "custom_rules/...") + parts = p.parts + if parts and parts[0] == custom_rules_path.name: + logger.debug(f"Skipping result from custom_rules directory: {path}") + continue + except Exception: + pass + except Exception: + pass + # Normalize path early to strip workspace/temp/custom_rules paths normalized_path = path try: @@ -302,8 +339,23 @@ def _convert_to_socket_facts(self, raw_results: Any) -> Dict[str, Any]: # Remove internal namespace prefix if present; connectors own # their emitted identifiers and must not expose internal pkg IDs try: - if isinstance(check_id, str) and check_id.startswith('socket_basics.rules.'): - check_id = check_id.replace('socket_basics.rules.', '', 1) + if isinstance(check_id, str): + # Remove socket_basics.rules. prefix from bundled rules + if check_id.startswith('socket_basics.rules.'): + check_id = check_id.replace('socket_basics.rules.', '', 1) + # Remove temp directory path prefix from custom rules + # Pattern: var.folders.nl.zptkx4wd7sv5kn9lbp_vbm980000gn.T.socket_custom_rules_XXXX.rule-name + # We want to extract just the rule-name part + elif '.socket_custom_rules_' in check_id: + # Find the last dot after socket_custom_rules_ to get the rule name + parts = check_id.split('.') + # Find index of part containing socket_custom_rules_ + for i, part in enumerate(parts): + if part.startswith('socket_custom_rules_'): + # Rule name is everything after this part + if i + 1 < len(parts): + check_id = '.'.join(parts[i+1:]) + break except Exception: pass severity = ((r.get('extra') or {}).get('severity') or r.get('severity') or '') diff --git a/socket_basics/version.py b/socket_basics/version.py index b931c6a..6e3c058 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.19" +__version__ = "1.0.20"