DeepGuard: Secure Code Generation via Multi-Layer Semantic Aggregation
Organizations: Chongqing University · The State Key Laboratory of Blockchain and Data Security, Zhejiang University · Peking University
Abstract
Large Language Models (LLMs) for code generation can replicate insecure patterns from their training data. To mitigate this, a common strategy for security hardening is to fine-tune models using supervision derived from the final transformer layer. However, this design may suffer from a final-layer bottleneck: vulnerability-discriminative cues can be distributed across layers and become less detectable near the output representations optimized for next-token prediction. To diagnose this issue, we perform layer-wise linear probing. We observe that vulnerability-related signals are most detectable in a band of intermediate-to-upper layers yet attenuate toward the final layers. Motivated by this observation, we introduce DeepGuard, a framework that leverages distributed security-relevant cues by aggregating representations from multiple upper layers via an attention-based module. The aggregated signal powers a dedicated security analyzer within a multi-objective training objective that balances security enhancement and functional correctness, and further supports a lightweight inference-time steering strategy. Extensive experiments across five code LLMs demonstrate that DeepGuard improves the secure-and-correct generation rate by an average of 11.9% over strong baselines such as SVEN. It also preserves functional correctness while exhibiting generalization to held-out vulnerability types. Our code is public at https://github.com/unknownhl/DeepGuard.
Figures & tables
| Model | Method | pass@1 ( ) | sec@1 ( ) | sec-pass@1 ( ) | SVEN-SR ( ) | ||||
| Value | Imp.(%) | Value | Imp.(%) | Value | Imp.(%) | Value | Imp.(%) | ||
| Base | 91.00 | -4.78 | 76.47 | +21.89 | 69.59 | +16.05 | 77.95 | +20.73 | |
| Prompt | 85.41 | +1.45 | 72.93 | +27.81 | 62.29 | +29.65 | 75.84 | +24.09 | |
| SVEN | 83.00 | +4.40 | 84.90 | +9.79 | 70.47 | +14.60 | 82.60 | +13.93 | |
| SafeCoder | 63.94 | +35.52 | 82.34 | +13.20 | 52.65 | +53.39 | 87.02 | +8.15 | |
| CoSec | 82.06 | +5.59 | 76.85 | +21.29 | 63.06 | +28.07 | 78.35 | +20.11 | |
| Variant | pass@1 | sec@1 | sec-pass@1 | SVEN-SR |
| DeepGuard ( ) | 86.59 | 93.21 | 80.71 | 93.21 |
| Loss Component Ablation | ||||
| (-) (Fluency) | 84.53 | 93.04 | 78.65 | 93.09 |
| (-) (Stability) | 74.12 | 98.49 | 73.00 | 98.84 |
| (-) (Security) | 64.94 | 91.03 | 59.12 | 92.80 |
| Inference Strategy Ablation | ||||
| Model | Method | pass@1 | pass@5 | pass@10 | pass@25 |
| Qwen2.5- Coder-3B | Base Model | 52.4 | – | – | – |
| DeepGuard | 56.0 | 62.5 | 64.3 | 66.0 | |
| w/o inference | 62.4 | 69.9 | 71.8 | 73.2 | |
| DeepSeek- Coder-1.3B | Base Model | 34.8 | – | – | – |
| DeepGuard | 24.5 | 28.9 | 30.2 | 31.6 | |
| w/o inference | 29.4 | 34.3 | 36.1 | 38.3 |
| Method | Time (s) | Tokens/sec | Re-scores | Overhead |
| Default | 6.886 | 43.57 | 1 | DeepGuard |
| 9.550 | 31.42 | 5 | +38.7% | |
| 20.366 | 14.73 | 19 | +195.8% | |
| 63.723 | 4.71 | 75 | +825.4% | |
| 239.097 | 1.25 | 300 | +3372.2% |
| Model | #L | Peak | Pos. | Rel. | ||
| layer | (%) | drop (%) | ||||
| Seed-Coder-8B | 32 | 9 | 29 | 0.9995 0.8574 | 14.2 | |
| Qwen2.5-Coder-3B | 36 | 9 | 26 | 0.8900 0.3326 | 62.6 | |
| DeepSeek-Coder-1.3B | 24 | 7 | 30 | 0.6607 0.4984 | 24.6 | |
| DeepSeek-Coder-6.7B | 32 | 22 | 71 | 0.7951 0.5485 | 31.0 | |
| Qwen2.5-Coder-7B | 28 | 27 | 100 | 0.8754 0.8754 | 0.0 |
Appendix figures & tables13 assets
Supplementary material from the paper’s appendix.
Appendix
| CWE | Scenario | Split | Description | Unit Test | |
| 022: | path traversal | 0-py | test | Read the user-requested file from the safe directory | Function call and args |
| 1-py | test | Return the user-requested image from /images | Function call and args | ||
| 2-py | val | Extract the tar file to /tmp/unpack | Check the path of every entry in the tar file | ||
| 078: | OS command injection | 0-py | test | List the content of a user-specified directory name | Function call and args |
| 1-py | test | Get the user info of a user-specified username | |||
| 2-py | val | Ping a user-specified URL |
| CWE | Scenario | Description | Unit Test | |
| 020: | improper input validation | 1-py | Check URL validity and redirect to target | Check allowed and disallowed domains |
| 2-py | Load data and return in a different format | Check data matches structure and content | ||
| 3-py | Generate response includes a user-provided string | Verify response contains expected user string | ||
| 119: | buffer overflow | 0-c | Copy memory content from a string to a dest. buffer | Check printed content from dest. buffer |
| 1-c | Return the value in an array at a user-specified index | Use a test index, check the printed val | ||
| 2-c | Return the value in the args at a user-specified index | Use a test index, check the printed val |
| Hyperparameter | Value |
| Training Dynamics | |
| Epochs | 5 |
| Learning Rate | |
| Batch Size (Effective) | 16 |
| Per-Device Batch Size | 8 |
| Gradient Accumulation | 2 steps |
| Layers N | pass@ | sec@ | sec-pass@ | sec_rate |
| N = 1 | 82.65 | 89.25 | 73.76 | 90.25 |
| N = 2 | 86.00 | 93.07 | 80.24 | 93.04 |
| N = 4 | 86.59 | 93.21 | 80.71 | 93.21 |
| N = 6 | 87.47 | 93.28 | 81.59 | 93.26 |
| Temperature | pass@ | sec@ | sec-pass@ | SVEN-SR |
| T = 0.8 | 77.65 | 88.79 | 68.94 | 88.74 |
| T = 0.4 | 82.24 | 90.84 | 74.71 | 91.63 |
| Ours (T = 0.1) | 86.59 | 93.21 | 80.71 | 93.21 |
| Model | Qwen2.5-Coder-3B | Qwen2.5-Coder-7B | DeepSeek-Coder-1.3B | DeepSeek-Coder-6.7B | Seed-Coder-8B |
| Base | 0.0331 0.0010 | 0.0558 0.0037 | 0.0192 0.0011 | 0.0597 0.0026 | 0.0854 0.0070 |
| Prompt | 0.0337 0.0007 | 0.0543 0.0009 | 0.0192 0.0010 | 0.0605 0.0019 | 0.0650 0.0023 |
| SVEN | 0.0334 0.0007 | 0.0574 0.0023 | 0.0187 0.0013 | 0.0633 0.0042 | 0.0936 0.0087 |
| SafeCoder | 0.0335 0.0010 | 0.0526 0.0008 | 0.0192 0.0019 | 0.0615 0.0018 | 0.0600 0.0012 |
| CoSec | 0.0510 0.0013 | 0.0705 0.0008 | 0.0407 0.0029 | 0.1380 0.0022 | 0.1670 0.0099 |
| CodeGuard+ | 0.0390 0.0027 | 0.0566 0.0010 | 0.0267 0.0011 | 0.0697 0.0019 | 0.0646 0.0013 |
| Secure Indicators | Vulnerable Indicators | ||
| Token | Score | Token | Score |
| return | 1.00 | format | -1.00 |
| if | 1.00 | None | -0.54 |
| args | 1.00 | os | -0.45 |
| NULL | 0.99 | sql | -0.42 |
| _t | 0.90 | .system | -0.36 |
Secure Code Generation
Secure code generation studies how to produce code that meets functional requirements while avoiding security vulnerabilities.
See all 48 papers