Ismail131 commited on
Commit
ae29d48
·
verified ·
1 Parent(s): 83a54cc

Upload folder using huggingface_hub

Browse files
README.md CHANGED
@@ -38,9 +38,10 @@ uvicorn server.app:app --host 0.0.0.0 --port 8000
38
  ### 3. Run Baseline Agent (inference.py)
39
  ```bash
40
  # In a new terminal
 
41
  API_BASE_URL=https://api.openai.com/v1 \
42
  MODEL_NAME=gpt-4o \
43
- HF_TOKEN=your_openai_key \
44
  python inference.py
45
  ```
46
 
 
38
  ### 3. Run Baseline Agent (inference.py)
39
  ```bash
40
  # In a new terminal
41
+ # In a new terminal
42
  API_BASE_URL=https://api.openai.com/v1 \
43
  MODEL_NAME=gpt-4o \
44
+ OPENAI_API_KEY=your_openai_key \
45
  python inference.py
46
  ```
47
 
client.py CHANGED
@@ -44,7 +44,7 @@ class AuditEnv(EnvClient[AuditAction, AuditObservation, AuditState]):
44
 
45
  return StepResult(
46
  observation=observation,
47
- reward=payload.get("reward"),
48
  done=payload.get("done", False),
49
  )
50
 
 
44
 
45
  return StepResult(
46
  observation=observation,
47
+ reward=payload.get("reward", 0.0),
48
  done=payload.get("done", False),
49
  )
50
 
contracts/easy_reentrancy.sol CHANGED
@@ -19,12 +19,11 @@ contract VulnerableBank {
19
  uint256 bal = balances[msg.sender];
20
  require(bal > 0, "No balance");
21
 
22
- // BUG: External call to an address before updating state
23
- // This is where the reentrancy attack occurs.
 
 
24
  (bool sent, ) = msg.sender.call{value: bal}("");
25
  require(sent, "Transfer failed");
26
-
27
- // State update happens AFTER the external call
28
- balances[msg.sender] = 0;
29
  }
30
  }
 
19
  uint256 bal = balances[msg.sender];
20
  require(bal > 0, "No balance");
21
 
22
+ // Effects: Update state BEFORE external call
23
+ balances[msg.sender] = 0;
24
+
25
+ // Interactions: External call after state update
26
  (bool sent, ) = msg.sender.call{value: bal}("");
27
  require(sent, "Transfer failed");
 
 
 
28
  }
29
  }
contracts/hard_complex.sol CHANGED
@@ -15,33 +15,27 @@ contract ComplexAudit {
15
  uint256 public totalReward;
16
 
17
  constructor(address _m) {
 
18
  manager = _m;
19
  }
20
 
21
  /**
22
  * @dev Simple push of data without gas checking.
23
- */
24
  function pushData(string memory d) public {
 
25
  data[msg.sender] = d;
26
  }
 
27
 
28
  /**
29
- * @dev Vulnerable setter for manager role.
30
- */
31
  function setManager(address nextManager) public {
32
- // BUG: Missing onlyOwner/onlyManager check!
33
- // Anyone can hijack the manager role.
34
  manager = nextManager;
35
  }
36
 
37
  /**
38
- * @dev Dangerous functionality allowing delegation.
39
- */
40
- function execute(address target, bytes memory callData) public {
41
- // BUG: Using delegatecall with user-supplied target and data.
42
- // This allows an attacker to execute ANY command on the contract's behalf,
43
- // effectively gaining full control over state and balance.
44
- (bool success, ) = target.delegatecall(callData);
45
  require(success, "Delegatecall failed");
46
  }
47
 
 
15
  uint256 public totalReward;
16
 
17
  constructor(address _m) {
18
+ require(_m != address(0), "Invalid manager address");
19
  manager = _m;
20
  }
21
 
22
  /**
23
  * @dev Simple push of data without gas checking.
 
24
  function pushData(string memory d) public {
25
+ require(bytes(d).length <= 1024, "Data too large");
26
  data[msg.sender] = d;
27
  }
28
+ }
29
 
30
  /**
 
 
31
  function setManager(address nextManager) public {
32
+ require(msg.sender == manager, "Not authorized");
33
+ require(nextManager != address(0), "Invalid address");
34
  manager = nextManager;
35
  }
36
 
37
  /**
38
+ // Removed: delegatecall to arbitrary targets is inherently unsafe
 
 
 
 
 
 
39
  require(success, "Delegatecall failed");
40
  }
41
 
graders/grader_hard.py CHANGED
@@ -12,8 +12,11 @@ def grade(action, ground_truth):
12
  score = 0.0
13
  feedback_parts = []
14
 
15
- gt_vulns = ground_truth["vulnerabilities"]
16
- agent_vulns = getattr(action, "vulnerabilities", [])
 
 
 
17
 
18
  matches = 0
19
  for gt in gt_vulns:
 
12
  score = 0.0
13
  feedback_parts = []
14
 
15
+ gt_vulns = ground_truth.get("vulnerabilities", [])
16
+ if isinstance(action, dict):
17
+ agent_vulns = action.get("vulnerabilities", [])
18
+ else:
19
+ agent_vulns = getattr(action, "vulnerabilities", [])
20
 
21
  matches = 0
22
  for gt in gt_vulns:
inference.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import requests
2
  from openai import OpenAI
3
  from dotenv import load_dotenv
 
1
+ import os
2
+ import json
3
  import requests
4
  from openai import OpenAI
5
  from dotenv import load_dotenv
server/Dockerfile CHANGED
@@ -33,25 +33,25 @@ WORKDIR /app/env
33
 
34
  # Ensure uv is available (for local builds where base image lacks it)
35
  RUN if ! command -v uv >/dev/null 2>&1; then \
36
- curl -LsSf https://astral.sh/uv/install.sh | sh && \
37
- mv /root/.local/bin/uv /usr/local/bin/uv && \
38
- mv /root/.local/bin/uvx /usr/local/bin/uvx; \
39
  fi
40
-
41
  # Install dependencies using uv sync
42
  # If uv.lock exists, use it; otherwise resolve on the fly
43
  RUN --mount=type=cache,target=/root/.cache/uv \
44
  if [ -f uv.lock ]; then \
45
- uv sync --frozen --no-install-project --no-editable; \
46
  else \
47
- uv sync --no-install-project --no-editable; \
48
  fi
49
 
50
  RUN --mount=type=cache,target=/root/.cache/uv \
51
  if [ -f uv.lock ]; then \
52
- uv sync --frozen --no-editable; \
53
  else \
54
- uv sync --no-editable; \
55
  fi
56
 
57
  # Final runtime stage
@@ -71,6 +71,11 @@ ENV PATH="/app/.venv/bin:$PATH"
71
  # Set PYTHONPATH so imports work correctly
72
  ENV PYTHONPATH="/app/env:$PYTHONPATH"
73
 
 
 
 
 
 
74
  # Health check
75
  HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
76
  CMD curl -f http://localhost:8000/health || exit 1
 
33
 
34
  # Ensure uv is available (for local builds where base image lacks it)
35
  RUN if ! command -v uv >/dev/null 2>&1; then \
36
+ curl -LsSf https://astral.sh/uv/install.sh | sh && \
37
+ mv /root/.local/bin/uv /usr/local/bin/uv && \
38
+ mv /root/.local/bin/uvx /usr/local/bin/uvx; \
39
  fi
40
+
41
  # Install dependencies using uv sync
42
  # If uv.lock exists, use it; otherwise resolve on the fly
43
  RUN --mount=type=cache,target=/root/.cache/uv \
44
  if [ -f uv.lock ]; then \
45
+ uv sync --frozen --no-install-project --no-editable; \
46
  else \
47
+ uv sync --no-install-project --no-editable; \
48
  fi
49
 
50
  RUN --mount=type=cache,target=/root/.cache/uv \
51
  if [ -f uv.lock ]; then \
52
+ uv sync --frozen --no-editable; \
53
  else \
54
+ uv sync --no-editable; \
55
  fi
56
 
57
  # Final runtime stage
 
71
  # Set PYTHONPATH so imports work correctly
72
  ENV PYTHONPATH="/app/env:$PYTHONPATH"
73
 
74
+ # Install curl for health checks
75
+ RUN apt-get update && \
76
+ apt-get install -y --no-install-recommends curl && \
77
+ rm -rf /var/lib/apt/lists/*
78
+
79
  # Health check
80
  HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
81
  CMD curl -f http://localhost:8000/health || exit 1
server/__init__.py CHANGED
@@ -1,8 +1,5 @@
1
  """Smart Contract Audit environment server components."""
2
 
3
- try:
4
- from .audit_environment import AuditEnvironment
5
- except ImportError:
6
- from audit_environment import AuditEnvironment
7
 
8
  __all__ = ["AuditEnvironment"]
 
1
  """Smart Contract Audit environment server components."""
2
 
3
+ from .audit_environment import AuditEnvironment
 
 
 
4
 
5
  __all__ = ["AuditEnvironment"]
tasks/task_hard.py CHANGED
@@ -4,7 +4,7 @@ import os
4
  DIR = os.path.dirname(os.path.abspath(__file__))
5
  CONTRACT_PATH = os.path.join(DIR, "..", "contracts", "hard_complex.sol")
6
 
7
- with open(CONTRACT_PATH, "r") as f:
8
  CONTRACT_CODE = f.read()
9
 
10
  HARD_TASK = {
 
4
  DIR = os.path.dirname(os.path.abspath(__file__))
5
  CONTRACT_PATH = os.path.join(DIR, "..", "contracts", "hard_complex.sol")
6
 
7
+ with open(CONTRACT_PATH, "r", encoding="utf-8") as f:
8
  CONTRACT_CODE = f.read()
9
 
10
  HARD_TASK = {
tasks/task_medium.py CHANGED
@@ -15,19 +15,19 @@ MEDIUM_TASK = {
15
  "vulnerabilities": [
16
  {
17
  "type": "unchecked return",
18
- "line": 21,
19
  "severity": "medium",
20
  "description": "Return value of external call is not checked"
21
  },
22
  {
23
  "type": "access control",
24
- "line": 26,
25
  "severity": "critical",
26
  "description": "Sensitive kill function lacks access control"
27
  },
28
  {
29
  "type": "logic flaw",
30
- "line": 34,
31
  "severity": "high",
32
  "description": "Insecure reward mechanism allowing anyone to claim"
33
  }
 
15
  "vulnerabilities": [
16
  {
17
  "type": "unchecked return",
18
+ "line": 24,
19
  "severity": "medium",
20
  "description": "Return value of external call is not checked"
21
  },
22
  {
23
  "type": "access control",
24
+ "line": 30,
25
  "severity": "critical",
26
  "description": "Sensitive kill function lacks access control"
27
  },
28
  {
29
  "type": "logic flaw",
30
+ "line": 42,
31
  "severity": "high",
32
  "description": "Insecure reward mechanism allowing anyone to claim"
33
  }