Skip to content

Chapter 7: Model Context Protocol (MCP) Justification

MIESC Integration with Artificial Intelligence Assistants


7.1 Introduction: The Human-Tool Interface Problem

7.1.1 Historical Context of Security Interfaces

Security analysis tools have evolved significantly in their technical capabilities over the past two decades, but their user interfaces have remained fundamentally anchored to the command-line paradigm inherited from early compilers and static analyzers. This disparity between internal sophistication and external accessibility represents a significant barrier to the adoption of security practices in software development.

Consider the typical workflow of a developer who wants to verify the security of a smart contract before deploying it:

  1. Install the tool (a process that may require resolving dependency conflicts)
  2. Learn the tool-specific command syntax
  3. Execute the analysis and capture output
  4. Interpret technical results (SWC codes, execution traces, SMT conditions)
  5. Investigate each finding to determine if it represents a real vulnerability
  6. Decide and apply the appropriate remediation

This process assumes specialized technical knowledge that exceeds the typical competencies of an application developer. The result, documented by Beller et al. (2016), is that "static analysis tools are underutilized in industrial practice due to usage friction and difficulty in interpreting results" (p. 12).

7.1.2 The Emergence of Conversational Interfaces

The appearance of large language models (LLMs) capable of maintaining coherent and contextually relevant dialogues opened a new possibility: using natural language as the primary interface for technical tools. Instead of learning specific commands, users could express their intent in everyday language and let an intelligent intermediary translate that intent into tool invocations.

This vision, however, faced a fundamental obstacle: LLMs are closed systems that operate exclusively on text. They cannot execute code, access file systems, or invoke external APIs. Their knowledge is frozen at the moment of training, with no ability to update or access real-time information.

7.1.3 Model Context Protocol: Anthropic's Solution

In November 2024, Anthropic published the Model Context Protocol (MCP), an open specification that defines how LLMs can interact safely and structurally with external tools and data. MCP solves the inherent limitations of LLMs through a protocol that:

  1. Discovers available tools: The LLM can query what tools are registered and what parameters each accepts.

  2. Invokes tools safely: Tool calls pass through a server that validates inputs, applies permissions, and limits access.

  3. Receives structured results: Results are returned to the LLM in a format it can process and interpret for the user.

  4. Maintains context between calls: The protocol preserves conversation state, enabling iterative analysis.

The decision to implement an MCP server in MIESC is based on the recognition that the main barrier to security tool adoption is not technical but usability. MCP allows MIESC to be accessible through Claude Desktop, transforming a collection of 25 specialized tools into a conversational security assistant.


7.2 Analysis of Alternatives: Why MCP

7.2.1 Alternatives Considered

Before adopting MCP, four alternatives were evaluated to enable interaction with AI assistants:

Alternative 1: Traditional REST API

A REST API would expose MIESC endpoints for consumption by any client. This option, effectively implemented in MIESC as a complementary interface, has universality advantages but lacks: - Automatic capability discovery - Intelligent orchestration of multiple calls - Contextual interpretation of results

The user or developer consuming the API must know beforehand what endpoints exist, what parameters they require, and how to interpret responses. The API provides no "intelligence" beyond literal execution of what is requested.

Alternative 2: ChatGPT Plugin

OpenAI allows developing plugins that extend ChatGPT's capabilities. This option was discarded for three reasons: 1. Vendor lock-in: The plugin would only work with ChatGPT, excluding other assistants 2. API cost: Requires ChatGPT Plus subscription and variable API costs 3. Code transmission: Contract source code would be transmitted to OpenAI servers

This last reason is particularly critical in the context of security audits, where code under analysis frequently contains confidential intellectual property or potentially exploitable vulnerabilities.

Alternative 3: Langchain Agent

Langchain is a Python framework for building applications that combine LLMs with external tools. A Langchain "agent" can invoke Python functions based on natural language descriptions.

Evaluation of this alternative revealed: - Setup complexity: Langchain requires extensive configuration and heavy dependencies - Abstraction overhead: Multiple layers of indirection add latency and failure points - LLM backend coupling: Although it supports multiple providers, agent code becomes tied to Langchain abstractions

Alternative 4: MCP Server (Selected)

MCP offers an optimal balance among alternatives:

Criterion REST API ChatGPT Plugin Langchain MCP
Open standard Yes No Partial Yes
Automatic discovery No Yes Partial Yes
Intelligent orchestration No Yes Yes Yes
Local execution Yes No Partial Yes
Native Claude support No No No Yes
Implementation complexity Low High High Medium

7.2.2 Decisive Factors for MCP

MCP selection was based on four factors:

1. Alignment with data sovereignty principles

MCP defines a model where the server (MIESC) runs on the user's infrastructure, and the client (Claude) connects locally. Source code never leaves the local system:

User -> Claude Desktop -> MCP Client -> localhost:3000 -> MIESC MCP Server -> Tools
                                                                |
                                                          (All local)

This model is fundamentally different from ChatGPT plugins, where data travels through third-party servers.

2. Open and stable specification

MCP is a specification published under a permissive license, with reference implementations in Python and TypeScript. The specification defines: - JSON-RPC 2.0 message format - Schemas for tool discovery - Authentication and permission protocols - Streaming mechanisms for large results

This openness guarantees that MIESC is not tied to future decisions of a single vendor.

3. Native Claude integration

Claude Desktop and Claude Code implement native MCP support, meaning integration with MIESC "just works" without additional client-side development. Claude users can access MIESC capabilities immediately after configuring the server.

4. Granular permission model

MCP defines a permission system that allows users to control what capabilities each server exposes: - File system access (read/write) - Command execution - Network access - Available resources

For MIESC, this allows configuring the server with read-only access to contract directories, without the ability to modify files or access other system parts.


7.3 MIESC MCP Server Architecture

7.3.1 Conceptual Design

The MIESC MCP server acts as a bridge between Claude's conversational world and the technical world of security analysis tools. Its responsibility is threefold:

  1. Translate intentions into invocations: When Claude determines it needs to analyze a contract, the server translates that intention into concrete calls to MIESC adapters.

  2. Normalize and contextualize results: Raw tool findings are transformed into interpretable descriptions that Claude can communicate to the user.

  3. Maintain session state: The server preserves context from previous analyses, enabling iterative refinement.

Figure 23. MCP integration architecture

Figure 23 - MCP integration architecture

Interaction flow between User, Claude Desktop and MIESC MCP Server

7.3.2 Server Components

1. Tools Handler

The tools handler exposes MIESC capabilities as "tools" invocable by Claude. Each tool is defined with: - Unique and descriptive name - Natural language description of its purpose - JSON schema for input parameters - Execution behavior

class MIESCToolHandler:
    """
    Exposes MIESC tools as MCP tools.

    Design follows the principle that each tool should be
    self-contained and descriptive: Claude should be able to determine
    when and how to use it based solely on its description.
    """

    def get_tools(self) -> list:
        """
        Returns the list of available tools.

        Descriptions are written so Claude understands:
        1. What the tool does
        2. When it's appropriate to use it
        3. What parameters it needs
        """
        return [
            {
                "name": "analyze_contract",
                "description": """Analyze a smart contract for security vulnerabilities
                using MIESC's 7-layer defense-in-depth architecture. This tool runs
                multiple analysis techniques including static analysis (Slither),
                symbolic execution (Mythril), fuzzing (Echidna), and AI-powered
                semantic analysis. Use this tool when the user wants a comprehensive
                security audit of their contract.""",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "contract_path": {
                            "type": "string",
                            "description": "Path to the Solidity contract file (.sol)"
                        },
                        "layers": {
                            "type": "array",
                            "items": {"type": "integer", "minimum": 1, "maximum": 7},
                            "description": "Specific layers to execute (1-7). Default: all layers"
                        },
                        "timeout": {
                            "type": "integer",
                            "description": "Maximum time in seconds for analysis. Default: 300"
                        }
                    },
                    "required": ["contract_path"]
                }
            },
            {
                "name": "run_slither",
                "description": """Run Slither static analyzer on a contract. Slither
                is fast (typically <5 seconds) and good for detecting common
                vulnerabilities like reentrancy, unchecked returns, and access
                control issues. Use this for quick initial scans.""",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "contract_path": {"type": "string"}
                    },
                    "required": ["contract_path"]
                }
            },
            # ... definitions for all 25 tools
        ]

2. Resources Handler

MCP resources represent data that Claude can query without executing analysis. In MIESC, resources include:

class MIESCResourceHandler:
    """
    Exposes MIESC informational resources.

    Resources allow Claude to access reference information
    (like the SWC database) without running analysis, reducing
    latency for informational queries.
    """

    def get_resources(self) -> list:
        return [
            {
                "uri": "miesc://swc-registry",
                "name": "SWC Registry",
                "description": """Complete Smart Contract Weakness Classification
                database with descriptions, examples, and remediation guidance
                for all known vulnerability types.""",
                "mimeType": "application/json"
            },
            {
                "uri": "miesc://tool-status",
                "name": "Tool Status",
                "description": """Current availability and version information
                for all 25 security tools integrated in MIESC.""",
                "mimeType": "application/json"
            },
            {
                "uri": "miesc://findings/latest",
                "name": "Latest Findings",
                "description": """Results from the most recent security analysis,
                including all detected vulnerabilities and their metadata.""",
                "mimeType": "application/json"
            }
        ]

7.3.3 Detailed Communication Flow

The following sequence diagram illustrates the complete flow of a typical interaction:

Figure 24. MCP interaction sequence

Figure 24 - MCP interaction sequence

User             Claude              MCP Client           MIESC Server          Slither
   |                   |                    |                     |                   |
   | "Analyze my       |                    |                     |                   |
   |  VulnerableBank"  |                    |                     |                   |
   |------------------>|                    |                     |                   |
   |                   |                    |                     |                   |
   |                   |   tools/list       |                     |                   |
   |                   |------------------>|                     |                   |
   |                   |                    |     getTools()      |                   |
   |                   |                    |------------------->|                   |
   |                   |                    |<-------------------|                   |
   |                   |<------------------|                     |                   |
   |                   |   [analyze_contract, run_slither, ...]   |                   |
   |                   |                    |                     |                   |
   |                   |   tools/call       |                     |                   |
   |                   |   analyze_contract |                     |                   |
   |                   |   {"contract_path":|                     |                   |
   |                   |    "VulnerableBank.sol"}                 |                   |
   |                   |------------------>|                     |                   |
   |                   |                    |    callTool()       |                   |
   |                   |                    |------------------->|                   |
   |                   |                    |                     |                   |
   |                   |                    |                     |   analyze()       |
   |                   |                    |                     |----------------->|
   |                   |                    |                     |<-----------------|
   |                   |                    |                     |   {findings:[...]}|
   |                   |                    |                     |                   |
   |                   |                    |<-------------------|                   |
   |                   |                    |   {findings: [...], |                   |
   |                   |                    |    summary: "..."}  |                   |
   |                   |<------------------|                     |                   |
   |                   |                    |                     |                   |
   |<------------------|                    |                     |                   |
   | "I found 5        |                    |                     |                   |
   |  vulnerabilities: |                    |                     |                   |
   |  1. Reentrancy    |                    |                     |                   |
   |     in withdraw() |                    |                     |                   |
   |  ..."             |                    |                     |                   |

7.4 Technical Implementation

7.4.1 Main MCP Server

# src/mcp/server.py
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, Resource, TextContent

from src.adapters import register_all_adapters, get_adapter_by_name
from src.mcp.tool_handler import MIESCToolHandler
from src.mcp.resource_handler import MIESCResourceHandler
from src.mcp.security import validate_contract_path, SecurityError

logger = logging.getLogger(__name__)

# MCP server instance
app = Server("miesc-security")
tool_handler = MIESCToolHandler()
resource_handler = MIESCResourceHandler()

@app.list_tools()
async def list_tools() -> list[Tool]:
    """
    List all tools available to Claude.

    This function is invoked when Claude needs to know what
    capabilities it has available. The result determines what
    actions Claude can propose to the user.
    """
    return tool_handler.get_tools()

@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    """
    Execute a MIESC tool.

    Execution process:
    1. Validate the tool exists
    2. Validate input parameters (especially paths)
    3. Execute the corresponding analysis
    4. Format results for Claude
    """
    logger.info(f"Tool invocation: {name} with args {arguments}")

    try:
        if name == "analyze_contract":
            contract_path = arguments.get("contract_path")
            layers = arguments.get("layers", [1, 2, 3, 4, 5, 6, 7])
            timeout = arguments.get("timeout", 300)

            # Critical security validation
            validate_contract_path(contract_path)

            # Execute multi-layer analysis
            results = await run_full_analysis(contract_path, layers, timeout)

            return [TextContent(
                type="text",
                text=format_findings_for_claude(results)
            )]

        elif name.startswith("run_"):
            # Individual tool invocation
            tool_name = name.replace("run_", "")
            adapter = get_adapter_by_name(tool_name)

            if adapter is None:
                raise ValueError(f"Unknown tool: {tool_name}")

            contract_path = arguments.get("contract_path")
            validate_contract_path(contract_path)

            result = await asyncio.to_thread(
                adapter.analyze,
                contract_path,
                timeout=arguments.get("timeout", 60)
            )

            return [TextContent(
                type="text",
                text=format_single_tool_result(result)
            )]

        else:
            raise ValueError(f"Unknown tool: {name}")

    except SecurityError as e:
        logger.warning(f"Security violation in tool call: {e}")
        return [TextContent(
            type="text",
            text=f"Security error: {e}. The requested operation was blocked."
        )]
    except Exception as e:
        logger.error(f"Error in tool execution: {e}", exc_info=True)
        return [TextContent(
            type="text",
            text=f"Analysis failed: {str(e)}"
        )]

@app.list_resources()
async def list_resources() -> list[Resource]:
    """List available informational resources."""
    return resource_handler.get_resources()

@app.read_resource()
async def read_resource(uri: str) -> str:
    """Read resource content."""
    return await resource_handler.read(uri)

async def main():
    """
    MCP server entry point.

    The server uses stdio (standard input/output) for
    communication with the MCP client. This allows Claude
    Desktop to launch the server as a subprocess and communicate
    directly without needing network sockets.
    """
    # Register all tool adapters
    register_all_adapters()

    logger.info("Starting MIESC MCP Server...")

    async with stdio_server() as (read_stream, write_stream):
        await app.run(
            read_stream,
            write_stream,
            app.create_initialization_options()
        )

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main())

7.4.2 Security Validation

Input validation is critical to prevent Claude, inadvertently or through manipulation, from executing unauthorized operations:

# src/mcp/security.py
import os
import re

class SecurityError(Exception):
    """Exception for security violations."""
    pass

# Security configuration
ALLOWED_EXTENSIONS = {'.sol'}
ALLOWED_PATHS = [
    os.path.expanduser("~/contracts"),
    os.path.expanduser("~/projects"),
    "/tmp/miesc"
]
MAX_FILE_SIZE = 1024 * 1024  # 1 MB

def validate_contract_path(path: str) -> bool:
    """
    Validate that the provided path is safe for analysis.

    Verifications performed:
    1. Does not contain path traversal sequences (../)
    2. Allowed file extension (.sol)
    3. Location within authorized directories
    4. File exists and is readable
    5. File does not exceed maximum size

    These verifications prevent:
    - Reading arbitrary system files
    - Executing malicious code packaged as .sol
    - Denial of service attacks via huge files
    """
    # Prevent path traversal
    if ".." in path:
        raise SecurityError("Path traversal detected: '..' not allowed")

    # Normalize and resolve path
    abs_path = os.path.abspath(os.path.expanduser(path))

    # Verify extension
    _, ext = os.path.splitext(abs_path)
    if ext.lower() not in ALLOWED_EXTENSIONS:
        raise SecurityError(f"Extension not allowed: {ext}. Only .sol files accepted")

    # Verify within allowed directory
    in_allowed_path = any(
        abs_path.startswith(os.path.abspath(allowed))
        for allowed in ALLOWED_PATHS
    )
    if not in_allowed_path:
        raise SecurityError(
            f"Path outside allowed directories. "
            f"Allowed: {ALLOWED_PATHS}"
        )

    # Verify existence
    if not os.path.exists(abs_path):
        raise SecurityError(f"File not found: {abs_path}")

    # Verify size
    size = os.path.getsize(abs_path)
    if size > MAX_FILE_SIZE:
        raise SecurityError(
            f"File too large: {size} bytes. "
            f"Maximum: {MAX_FILE_SIZE} bytes"
        )

    return True

7.4.3 Claude Desktop Configuration

For Claude Desktop to recognize the MIESC server, it is configured in the MCP configuration file:

// ~/.config/claude/claude_desktop_config.json (Linux/Mac)
// %APPDATA%\claude\claude_desktop_config.json (Windows)
{
  "mcpServers": {
    "miesc": {
      "command": "python",
      "args": ["-m", "src.mcp.server"],
      "cwd": "/path/to/miesc",
      "env": {
        "PYTHONPATH": "/path/to/miesc",
        "OLLAMA_HOST": "http://localhost:11434"
      }
    }
  }
}

7.5 Use Cases and Interaction Examples

7.5.1 Complete Interactive Audit

The following dialogue illustrates how a developer without security experience can obtain a comprehensive audit:

User: I have a staking contract in contracts/Staking.sol that I need to
      audit before deploying to mainnet. It's my first deploy and
      I want to make sure it has no critical vulnerabilities.

Claude: I will analyze your staking contract with a complete security
        audit. This will run multiple analysis tools including static
        analysis, symbolic execution, and AI-powered semantic analysis.

        [Executes: analyze_contract("contracts/Staking.sol", layers=[1,2,3,5,7])]

        I completed the analysis. I found 8 findings that need your attention:

        CRITICAL (2 - Block deployment):

        1. Reentrancy in unstake() - Line 67
           The contract transfers ETH before updating user balance.
           This allows an attacker to withdraw funds multiple times in a
           single transaction.

           Vulnerable code:
           ```solidity
           function unstake() external {
               uint256 amount = stakes[msg.sender];
               payable(msg.sender).transfer(amount);  // <- Transfer first
               stakes[msg.sender] = 0;                 // <- Update after
           }
           ```

           Impact: An attacker could drain all contract funds.
           Severity: CRITICAL

        2. Precision loss in calculateRewards() - Line 89
           Division is performed before multiplication, causing
           decimal loss that favors the protocol over users.

           Problematic code:
           ```solidity
           uint256 reward = (stakedAmount / totalStaked) * rewardPool;
           ```

           Impact: Users receive less rewards than they deserve,
           especially with small stakes.
           Severity: CRITICAL

        HIGH (3):
        [...]

        Would you like me to show you the corrected code for the critical findings?

User: Yes, show me how to fix the reentrancy problem

Claude: Here is the fix for the reentrancy vulnerability.
        There are two complementary approaches I recommend using together:

        Approach 1: Checks-Effects-Interactions Pattern

        ```solidity
        function unstake() external {
            uint256 amount = stakes[msg.sender];
            require(amount > 0, "Nothing to unstake");

            // EFFECTS: Update state BEFORE external interaction
            stakes[msg.sender] = 0;
            totalStaked -= amount;

            // INTERACTIONS: Transfer after updating state
            (bool success, ) = payable(msg.sender).call{value: amount}("");
            require(success, "Transfer failed");

            emit Unstaked(msg.sender, amount);
        }
        ```

        Approach 2: Add OpenZeppelin ReentrancyGuard (recommended)

        ```solidity
        import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

        contract Staking is ReentrancyGuard {
            function unstake() external nonReentrant {
                uint256 amount = stakes[msg.sender];
                require(amount > 0, "Nothing to unstake");

                stakes[msg.sender] = 0;
                totalStaked -= amount;

                (bool success, ) = payable(msg.sender).call{value: amount}("");
                require(success, "Transfer failed");

                emit Unstaked(msg.sender, amount);
            }
        }
        ```

        I recommend using both approaches: the CEI pattern as coding
        practice and ReentrancyGuard as additional defense. Defense
        in depth is especially important when funds are at stake.

        Would you like me to analyze the contract again after you make
        corrections to verify they're correct?

7.5.2 Contextual Documentation Query

User: What is SWC-107 and why is it so dangerous?

Claude: [Executes: read_resource("miesc://swc-registry")]

        SWC-107: Reentrancy

        Description:
        A reentrancy vulnerability occurs when a contract makes an
        external call to another contract before updating its own
        state. The external contract can then "re-enter" the
        original function before the first execution finishes.

        Why it's dangerous:

        1. Devastating financial impact: The DAO attack in 2016 exploited
           exactly this vulnerability, resulting in the loss of
           $60 million dollars and causing an Ethereum fork.

        2. Difficult to detect manually: The execution flow is
           counter-intuitive. The code "looks fine" because operations
           are in logical order, but actual execution order is different.

        3. Easy to exploit: Once identified, the vulnerability can
           be exploited with a relatively simple attacker contract.

        Vulnerable pattern:
        ```
        function withdraw() {
            uint balance = balances[msg.sender];
            msg.sender.call{value: balance}("");  // <- Attacker re-enters here
            balances[msg.sender] = 0;              // <- Never executes until the end
        }
        ```

        Notable historical incidents:
        - The DAO (2016): $60M lost, Ethereum fork
        - Cream Finance (2021): $130M lost
        - Rari Capital (2022): $80M lost

        This vulnerability remains one of the most exploited in DeFi
        because it's easy to introduce accidentally and traditional
        tools don't always detect it in complex contexts.

7.6 Demonstrated Benefits

7.6.1 Friction Reduction

Table 7.1. Workflow comparison

Task Without MCP (traditional CLI) With MCP (Claude)
Audit contract 5 commands, 10+ minutes 1 message, 2 minutes
Interpret findings Manual, requires expertise Contextual explanation
Get remediation Search external documentation Corrected code in-situ
Second opinion Run another tool "Confirm with Mythril"
Generate report Custom script "Generate an executive report"

7.6.2 Access Democratization

The MCP model allows developers without specific smart contract security training to:

  1. Understand vulnerabilities in their context: Claude explains not only what's wrong but why it matters and what could happen.

  2. Receive specific remediation guidance: Instead of generic documentation, they get corrected code for their particular case.

  3. Learn while working: Each interaction is a learning opportunity about smart contract security.

  4. Validate corrections: They can verify their changes effectively resolve the detected problem.


7.7 Limitations and Considerations

7.7.1 Technical Limitations

Limitation Impact Mitigation
Claude dependency Only works with Claude Desktop/Code REST API as fallback
Recent protocol (2024) Possible specification changes Abstraction in handlers
Analysis latency Waits during long analyses Progress streaming
Limited Claude context Very large contracts may truncate Intelligent chunking

7.7.2 Security Considerations

1. The MCP server should only listen on localhost:

# Secure configuration
MCP_CONFIG = {
    "host": "127.0.0.1",
    "transport": "stdio"  # Preferred over TCP
}

# INSECURE configuration - NEVER do this:
# MCP_CONFIG = {"host": "0.0.0.0", "port": 3000}

2. Always validate input paths to prevent access to files outside authorized scope.

3. Limit execution resources (time, memory) to prevent denial of service.

4. Maintain audit logs of all invocations for traceability.


7.8 Conclusions

7.8.1 Justification Summary

The MCP server implementation in MIESC addresses a real and significant problem: the gap between the sophistication of security analysis tools and their accessibility for typical developers. MCP enables closing this gap by providing a conversational interface that:

  1. Reduces entry barrier: Developers can access professional security analysis without learning specific commands or interpreting cryptic technical output.

  2. Maintains data sovereignty: All processing occurs locally, without transmitting source code to external services.

  3. Leverages existing intelligence: Claude contributes explanation, contextualization, and guidance capabilities that individual tools cannot provide.

  4. Is extensible and open: Based on an open specification, it does not create dependency on a specific vendor.

7.8.2 MIESC Positioning

The combination of 25 security tools, sovereign LLM (Ollama), and conversational interface (MCP) positions MIESC as:

The first smart contract security framework with native conversational AI integration, maintaining data sovereignty through completely local execution.

This value proposition is unique in the blockchain security ecosystem, where alternatives require sending code to external services, have significant costs, or lack accessible interfaces for non-specialists.


7.9 Chapter References

Anthropic. (2024). Model Context Protocol Specification. https://github.com/anthropics/mcp

Anthropic. (2024). MCP Servers Documentation. https://modelcontextprotocol.io/

Beller, M., Gousios, G., Panichella, A., & Zaidman, A. (2016). When, how, and why developers (do not) test in their IDEs. ESEC/FSE 2016, 179-190.

OWASP. (2023). Smart Contract Security Testing Guide. https://owasp.org/

Ross, R., et al. (2016). Guide to Industrial Control Systems (ICS) Security. NIST SP 800-82 Rev. 2.


Note: References follow APA 7th edition format. Document updated: 2025-11-29