crytic / slither-action

GNU Affero General Public License v3.0
127 stars 19 forks source link

Hard to understand Slither CI error (KeyError: 2450) #42

Closed nathandem closed 1 year ago

nathandem commented 1 year ago

We get this error in the CI, which doesn't seem related to our code. But it doesn't fail when running slither locally.

Here's the error:

/usr/bin/docker run --name c05bfe629341a69408c05218a2ce6b_a2823b --label 290506 --workdir /github/workspace --rm -e "NODOCKER" -e "INPUT_IGNORE-COMPILE" -e "INPUT_NODE-VERSION" -e "INPUT_SLITHER-CONFIG" -e "INPUT_SOLC-VERSION" -e "INPUT_TARGET" -e "INPUT_SARIF" -e "INPUT_SLITHER-ARGS" -e "INPUT_SLITHER-VERSION" -e "INPUT_FAIL-ON" -e "INPUT_INTERNAL-GITHUB-WORKSPACE" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/protocol/protocol":"/github/workspace" 290506:94c05bfe629341a69408c05218a2ce6b  "." "" "16" "" ""
Collecting wheel
  Downloading wheel-0.38.4-py3-none-any.whl (36 kB)
Installing collected packages: wheel
Successfully installed wheel-0.38.4
Collecting slither-analyzer
  Downloading slither_analyzer-0.9.1-py3-none-any.whl (615 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 615.0/615.0 KB 79.4 MB/s eta 0:00:00
Collecting pysha3>=1.0.2
  Downloading pysha3-1.0.2.tar.gz (829 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 829.2/829.2 KB 231.8 MB/s eta 0:00:00
  Preparing metadata (setup.py): started
  Preparing metadata (setup.py): finished with status 'done'
Collecting prettytable>=0.7.2
  Downloading prettytable-3.5.0-py3-none-any.whl (26 kB)
Collecting crytic-compile>=0.2.4
  Downloading crytic_compile-0.2.4-py3-none-any.whl (87 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 87.7/87.7 KB 199.6 MB/s eta 0:00:00
Collecting wcwidth
  Downloading wcwidth-0.2.5-py2.py3-none-any.whl (30 kB)
Building wheels for collected packages: pysha3
  Building wheel for pysha3 (setup.py): started
  Building wheel for pysha3 (setup.py): finished with status 'done'
  Created wheel for pysha3: filename=pysha3-1.0.2-cp39-cp39-linux_x86_64.whl size=146824 sha256=ce4a902d2b9706c88078c8ae0fea52b8bbb828f73f03b985d1a04280c339e57f
  Stored in directory: /tmp/pip-ephem-wheel-cache-qlls3_e8/wheels/17/9d/00/86e22a32b0109bd3c8797adf[13](https://github.com/Finance/protocol/actions/runs/3495715128/jobs/5852902571#step:8:14)a74427aa38e6ad1135633d50
Successfully built pysha3
Installing collected packages: wcwidth, pysha3, prettytable, crytic-compile, slither-analyzer
Successfully installed crytic-compile-0.2.4 prettytable-3.5.0 pysha3-1.0.2 slither-analyzer-0.9.1 wcwidth-0.2.5
[-] Applied compatibility link: /home/runner/work/protocol/protocol -> /github/workspace
[-] Slither config provided: slither.config.json
Traceback (most recent call last):
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 826, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 97, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 75, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/opt/slither/lib/python3.9/site-packages/slither/slither.py", line 102, in __init__
    parser.parse_top_level_from_loaded_json(ast, path)
  File "/opt/slither/lib/python3.9/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 211, in parse_top_level_from_loaded_json
    contract.set_offset(top_level_data["src"], self._compilation_unit)
  File "/opt/slither/lib/python3.9/site-packages/slither/core/source_mapping/source_mapping.py", line 184, in set_offset
    self.source_mapping = _convert_source_mapping(offset, compilation_unit)
  File "/opt/slither/lib/python3.9/site-packages/slither/core/source_mapping/source_mapping.py", line [15](https://github.com/Finance/protocol/actions/runs/3495715128/jobs/5852902571#step:8:16)0, in _convert_source_mapping
    (lines, starting_column, ending_column) = _compute_line(compilation_unit, filename, s, l)
  File "/opt/slither/lib/python3.9/site-packages/slither/core/source_mapping/source_mapping.py", line 111, in _compute_line
    end_line, ending_column = compilation_unit.core.crytic_compile.get_line_from_offset(
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 291, in get_line_from_offset
    return lines_delimiters[offset]
KeyError: 2450
Error in .
Traceback (most recent call last):
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 826, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 97, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 75, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/opt/slither/lib/python3.9/site-packages/slither/slither.py", line 102, in __init__
    parser.parse_top_level_from_loaded_json(ast, path)
  File "/opt/slither/lib/python3.9/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 211, in parse_top_level_from_loaded_json
    contract.set_offset(top_level_data["src"], self._compilation_unit)
  File "/opt/slither/lib/python3.9/site-packages/slither/core/source_mapping/source_mapping.py", line [18](https://github.com/Finance/protocol/actions/runs/3495715128/jobs/5852902571#step:8:19)4, in set_offset
    self.source_mapping = _convert_source_mapping(offset, compilation_unit)
  File "/opt/slither/lib/python3.9/site-packages/slither/core/source_mapping/source_mapping.py", line 150, in _convert_source_mapping
    (lines, starting_column, ending_column) = _compute_line(compilation_unit, filename, s, l)
  File "/opt/slither/lib/python3.9/site-packages/slither/core/source_mapping/source_mapping.py", line 111, in _compute_line
    end_line, ending_column = compilation_unit.core.crytic_compile.get_line_from_offset(
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 291, in get_line_from_offset
    return lines_delimiters[offset]
KeyError: [24]

Here's our github action:

name: Slither Analysis

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    env:
      NODOCKER: 1
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: 'yarn'
      - uses: actions/cache@v3
        with:
          path: |
            cache
            artifacts
            typechain
            forge-cache
            out
          key: ${{ runner.OS }}-contracts-${{ hashFiles('contracts/*.sol', 'contracts/**/*.sol') }}
          restore-keys: |
            ${{ runner.OS }}-contracts-

      - name: Installing dependencies
        run: yarn install --prefer-offline --frozen-lockfile

      - name: Compile and create artifacts
        run: yarn compile

      - name: Run Slither
        uses: crytic/slither-action@v0.2.0
        id: slither
        with:
          ignore-compile: true
          node-version: 16
          slither-config: slither.config.json

The error happens are the "Run Slither" step.

Any idea?

elopez commented 1 year ago

Hi @nathandem! Thanks for the report. Here are few questions to try and narrow the issue down:

name: Slither Analysis

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    env:
      NODOCKER: 1
    steps:
      - uses: actions/checkout@v3

      - name: Run Slither
        uses: crytic/slither-action@v0.2.0
        id: slither
        with:
          node-version: 16
          slither-config: slither.config.json
markus0x1 commented 1 year ago

We are using slither 0.9.1 both in CI and locally. We use both foundry and hardhat in our project. When we let slither compile, it fails when it tries to install the dependencies from the foundry.toml:

yarn install v1.22.19
[1/5] Validating package.json...
[2/5] Resolving packages...
[3/5] Fetching packages...
[4/5] Linking dependencies...
warning " > @matterlabs/hardhat-zksync-solc@0.3.11-beta.1" has incorrect peer dependency "hardhat@^2.12.1".
warning " > @nomiclabs/hardhat-waffle@2.0.3" has incorrect peer dependency "ethereum-waffle@^3.2.0".
warning " > @primitivefi/hardhat-dodoc@0.2.3" has unmet peer dependency "squirrelly@^8.0.8".
warning " > @typechain/ethers-v5@10.1.0" has unmet peer dependency "@ethersproject/abi@^5.0.0".
warning " > @typechain/ethers-v5@10.1.0" has unmet peer dependency "@ethersproject/bytes@^5.0.0".
warning " > @typechain/ethers-v5@10.1.0" has unmet peer dependency "@ethersproject/providers@^5.0.0".
warning " > @typechain/hardhat@6.1.3" has unmet peer dependency "@ethersproject/abi@^5.4.7".
warning " > @typechain/hardhat@6.1.3" has unmet peer dependency "@ethersproject/providers@^5.4.7".
warning " > prb-math@2.4.3" has unmet peer dependency "@ethersproject/bignumber@5.x".
warning " > prb-math@2.4.3" has unmet peer dependency "evm-bn@1.x".
warning " > prb-math@2.4.3" has unmet peer dependency "mathjs@10.x".
[5/5] Building fresh packages...
$ node scripts/postinstall.js
Running postinstall script...
check out from github
Cloning into 'forge-std'...
Already on 'master'
Submodule 'lib/ds-test' (https://github.com/dapphub/ds-test) registered for path 'lib/ds-test'
Cloning into '/github/workspace/node_modules/forge-std/lib/ds-test'...
installing...
postinstall complete.
$ node ./.setup.js && test -n "$NODOCKER" || yarn update-local
Done in 48.60s.
[-] Installing dependencies from requirements.txt in a venv
Collecting wheel
  Downloading wheel-0.38.4-py3-none-any.whl (36 kB)
Installing collected packages: wheel
Successfully installed wheel-0.38.4
Collecting asttokens==2.0.5
  Downloading asttokens-2.0.5-py2.py3-none-any.whl (20 kB)
Collecting pycryptodome==3.15.0
  Downloading pycryptodome-3.15.0-cp35-abi3-manylinux2010_x86_64.whl (2.3 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.3/2.3 MB 71.4 MB/s eta 0:00:00
Collecting semantic-version==2.8.5
  Downloading semantic_version-2.8.5-py2.py3-none-any.whl (15 kB)
Collecting six==1.16.0
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting vyper==0.3.3
  Downloading vyper-0.3.3-py3-none-any.whl (261 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 261.3/261.3 KB 303.4 MB/s eta 0:00:00
Requirement already satisfied: wheel in /opt/dependencies/lib/python3.9/site-packages (from vyper==0.3.3->-r requirements.txt (line 5)) (0.38.4)
Installing collected packages: six, semantic-version, pycryptodome, asttokens, vyper
Successfully installed asttokens-2.0.5 pycryptodome-3.15.0 semantic-version-2.8.5 six-1.16.0 vyper-0.3.3
[-] Installing dependencies from foundry.toml
Error: 
error: pathspec '/github/workspace/lib' did not match any file(s) known to git

foundry.toml

[profile.default]
ffi = false
fuzz_runs = 256
optimizer = true
optimizer_runs = 999999
remappings = ["ds-test/=node_modules/forge-std/lib/ds-test/src", "hardhat/=node_modules/hardhat/","@openzeppelin/=node_modules/@openzeppelin/","hardhat-deploy/=node_modules/hardhat-deploy/", "forge-std/=node_modules/forge-std/src/", "util-contracts/=node_modules/@gnosis.pm/util-contracts/contracts/"]
verbosity = 1
libs = ['node_modules']
src = "contracts/"
test = 'test/foundry'
out = 'out'
cache_path  = 'forge-cache'
solc = '0.8.16' # set solc version
# auto_detect_solc = true

slither.yml

name: Slither Analysis

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    env:
      NODOCKER: 1
    steps:
      - uses: actions/checkout@v3

      - name: Run Slither
        uses: crytic/slither-action@v0.2.0
        id: slither
        with:
          node-version: 16
          slither-config: slither.config.json
elopez commented 1 year ago

That foundry error you got is not from the action itself -- all the action does there is forge install. Can you confirm if that works on a fresh clone of the repository, after running yarn install?

As for your original workflow, does yarn compile run hardhat build? Do you have "compile_force_framework": "hardhat" set in your slither config?

markus0x1 commented 1 year ago

You are right, executing forge install fails in any case. Can you avoid executing the command? We install dependencies with yarn.

To compile the contracts we use hardhat: "compile": "hardhat compile",

We dont have "compile_force_framework": "hardhat" set. slither.config.json:

{
  "detectors_to_exclude": "timestamp,solc-version",
  "filter_paths": "test|mocks"
}
elopez commented 1 year ago

The only way right now to skip running it is not having a foundry.toml file -- you could try adding a step like the following before running the slither action. This will make it skip the foundry dependency part.

      - name: Disable foundry
        run: rm foundry.toml
markus0x1 commented 1 year ago

That failed for me with the following error:

An unexpected error occurred:
[Error: EACCES: permission denied, mkdir '/github/home/.cache/hardhat-nodejs'] {
  errno: -13,
  code: 'EACCES',
  syscall: 'mkdir',
  path: '/github/home/.cache/hardhat-nodejs'
}
Traceback (most recent call last):
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 826, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 86, in process_all
    compilations = compile_all(target, **vars(args))
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 637, in compile_all
    compilations.append(CryticCompile(target, **kwargs))
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 117, in __init__
    self._compile(**kwargs)
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 548, in _compile
    self._platform.compile(self, **kwargs)
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/platform/hardhat.py", line 92, in compile
    os.listdir(build_directory), key=lambda x: os.path.getmtime(Path(build_directory, x))
FileNotFoundError: [Errno 2] No such file or directory: 'artifacts/build-info'
Error in .
Traceback (most recent call last):
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 826, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/opt/slither/lib/python3.9/site-packages/slither/__main__.py", line 86, in process_all
    compilations = compile_all(target, **vars(args))
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 637, in compile_all
    compilations.append(CryticCompile(target, **kwargs))
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 117, in __init__
    self._compile(**kwargs)
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/crytic_compile.py", line 548, in _compile
    self._platform.compile(self, **kwargs)
  File "/opt/slither/lib/python3.9/site-packages/crytic_compile/platform/hardhat.py", line 92, in compile
    os.listdir(build_directory), key=lambda x: os.path.getmtime(Path(build_directory, x))
FileNotFoundError: [Errno 2] No such file or directory: 'artifacts/build-info'
markus0x1 commented 1 year ago

I did some more digging and slither runs with the previous slither.yml when removing restore-keys.

name: Slither Analysis

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    env:
      NODOCKER: 1
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: 'yarn'
      - uses: actions/cache@v3
        with:
          path: |
            cache
            artifacts
          key: ${{ runner.OS }}-contracts-slither-${{ hashFiles('contracts/*.sol', 'contracts/**/*.sol', 'hardhat.config.ts', 'yarn.lock') }}

      - name: Installing dependencies
        run: yarn install --prefer-offline --frozen-lockfile

      - name: Compile and create artifacts
        run: yarn compile

      - name: Run Slither
        uses: crytic/slither-action@v0.2.0
        id: slither
        with:
          ignore-compile: true
          node-version: 16
          slither-config: slither.config.json

Thanks for the help :+1:

markus0x1 commented 1 year ago

So Slither fails if the artifacts used are from different compiler runs. Happy to close the issue if this is the expected behavior.

elopez commented 1 year ago

If you can reproduce it outside of the action with different runs, it might be worth reporting in the slither issue tracker, and we can close this issue. But as a general thing, artifacts can usually go out of sync with the code if you modify and recompile (eg leftover artifacts from previous runs that don't get cleaned up), and it's best if you generate them from scratch before an analysis.