Runtime Resource Management Control Element in a Component Built to Run on Application Servers

Description

Runtime Resource Management Control Element in a Component Built to Run on Application Servers occurs when an application component that is designed to run on an application server (J2EE, ASP.NET, etc.) directly manages runtime resources such as threads, sockets, database connections, or file handles. Application servers provide managed resource pools and lifecycle management precisely because unmanaged resource creation can lead to resource exhaustion, thread safety issues, and conflicts with the container's resource management. Components should use container-managed resources through JNDI lookups, dependency injection, or other container-provided mechanisms.

Risk

Directly managing resources bypasses the application server's resource pooling and monitoring. This can lead to connection pool exhaustion when components create their own connections. Thread creation outside the container can cause thread leaks and resource exhaustion. Security contexts may not be properly propagated to manually created threads. The container cannot enforce security policies on unmanaged resources. Resource leaks become likely as the container cannot clean up resources it doesn't manage. Denial of service becomes easier when resource limits are not enforced. Debug and monitoring tools lose visibility into unmanaged resources.

Solution

Use container-managed resources through dependency injection or JNDI lookups. For database connections, use DataSource from JNDI rather than creating direct JDBC connections. Use container-managed thread pools (ManagedExecutorService in Java EE) instead of creating threads directly. Let the container manage connection pooling and lifecycle. Use container-provided APIs for asynchronous operations. Configure resource pools in the application server rather than in application code. Follow the application server's best practices for resource management. Use @Resource annotation for injection of container-managed resources.

Common Consequences

ImpactDetails
AvailabilityScope: Availability

DoS: Resource Consumption - Unmanaged resources can exhaust system resources and cause denial of service.
OtherScope: Other

Reduce Reliability - Resources not managed by the container may not be properly cleaned up.
Access ControlScope: Access Control

Bypass Protection Mechanism - Security contexts may not be properly propagated to unmanaged threads.

Example Code

Vulnerable Code

// Vulnerable: Creating threads directly in J2EE component
@WebServlet("/process")
public class VulnerableProcessingServlet extends HttpServlet {

    // Vulnerable: Creating thread pool directly
    private ExecutorService executor = Executors.newFixedThreadPool(10);

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        String data = req.getParameter("data");

        // Vulnerable: Submitting to unmanaged thread pool
        executor.submit(() -> {
            // Security context not propagated!
            // Container cannot monitor this thread
            processData(data);
        });

        // Vulnerable: Creating raw thread
        Thread worker = new Thread(() -> {
            // This thread is invisible to container
            // No resource limits enforced
            heavyProcessing();
        });
        worker.start();  // Thread leak potential!

        resp.getWriter().write("Processing started");
    }

    // Vulnerable: Thread pool never properly shut down
}
// Vulnerable: Direct JDBC connection management in EJB
@Stateless
public class VulnerableUserRepository {

    // Vulnerable: Hardcoded connection parameters
    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/users";
    private static final String USERNAME = "app_user";
    private static final String PASSWORD = "secret123";

    public User findById(Long id) {
        Connection conn = null;
        try {
            // Vulnerable: Creating connection directly
            // Bypasses container's connection pool!
            conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);

            PreparedStatement stmt = conn.prepareStatement(
                "SELECT * FROM users WHERE id = ?"
            );
            stmt.setLong(1, id);

            ResultSet rs = stmt.executeQuery();
            // ... process result

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // May not be called if exception occurs differently
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    // Connection leak!
                }
            }
        }
        return null;
    }
}
// Vulnerable: Direct socket management in web component
@WebServlet("/notify")
public class VulnerableNotificationServlet extends HttpServlet {

    // Vulnerable: Managing sockets directly
    private ServerSocket serverSocket;
    private List<Socket> clientSockets = new ArrayList<>();

    @Override
    public void init() throws ServletException {
        try {
            // Vulnerable: Creating server socket in servlet
            // Container cannot manage this resource!
            serverSocket = new ServerSocket(9999);

            // Vulnerable: Starting acceptor thread directly
            new Thread(() -> {
                while (!serverSocket.isClosed()) {
                    try {
                        Socket client = serverSocket.accept();
                        clientSockets.add(client);  // Not thread-safe!
                    } catch (IOException e) {
                        // Silently failing
                    }
                }
            }).start();

        } catch (IOException e) {
            throw new ServletException("Failed to start socket", e);
        }
    }

    @Override
    public void destroy() {
        // May not be called, leaving resources leaked
        try {
            serverSocket.close();
            for (Socket s : clientSockets) {
                s.close();
            }
        } catch (IOException e) {
            // Resources leaked
        }
    }
}
// Vulnerable: Direct resource management in ASP.NET
public class VulnerableDataController : ApiController
{
    // Vulnerable: Creating SqlConnection directly
    public async Task<IHttpActionResult> GetData(int id)
    {
        // Vulnerable: Hardcoded connection string
        string connStr = "Server=localhost;Database=mydb;User=sa;Password=secret;";

        // Vulnerable: Not using connection pooling properly
        using (var connection = new SqlConnection(connStr))
        {
            await connection.OpenAsync();

            // Vulnerable: Starting background thread
            Task.Run(() => {
                // No HttpContext available
                // No request cancellation token
                // Security context lost
                LogAnalytics(id);
            });

            // ... rest of processing
        }

        return Ok();
    }

    // Vulnerable: Creating background threads directly
    private static Thread backgroundWorker;

    static VulnerableDataController()
    {
        // Vulnerable: Static thread creation
        backgroundWorker = new Thread(BackgroundProcess);
        backgroundWorker.IsBackground = true;
        backgroundWorker.Start();  // Thread leak on app domain unload
    }
}

Fixed Code

// Fixed: Using container-managed resources in J2EE
@WebServlet("/process")
public class FixedProcessingServlet extends HttpServlet {

    // Fixed: Inject container-managed executor service
    @Resource
    private ManagedExecutorService executorService;

    // Fixed: Alternative - lookup from JNDI
    // @Resource(lookup = "java:comp/DefaultManagedExecutorService")
    // private ManagedExecutorService executorService;

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        String data = req.getParameter("data");

        // Fixed: Use container-managed executor
        // Security context is propagated automatically
        executorService.submit(() -> {
            // Container manages thread lifecycle
            // Security context available
            processData(data);
        });

        // Fixed: For scheduled tasks, use ManagedScheduledExecutorService
        // @Resource
        // private ManagedScheduledExecutorService scheduledExecutor;

        resp.getWriter().write("Processing started");
    }

    // No cleanup needed - container manages resources
}
// Fixed: Using container-managed DataSource in EJB
@Stateless
public class FixedUserRepository {

    // Fixed: Inject container-managed DataSource
    @Resource(lookup = "java:jboss/datasources/UsersDS")
    private DataSource dataSource;

    // Alternative: Use JPA with container-managed EntityManager
    @PersistenceContext
    private EntityManager entityManager;

    public User findById(Long id) {
        // Fixed: Using JPA - cleanest approach
        return entityManager.find(User.class, id);
    }

    public User findByIdJdbc(Long id) {
        // Fixed: If JDBC needed, use container-managed DataSource
        try (Connection conn = dataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(
                 "SELECT * FROM users WHERE id = ?")) {

            stmt.setLong(1, id);

            try (ResultSet rs = stmt.executeQuery()) {
                if (rs.next()) {
                    return mapUser(rs);
                }
            }

        } catch (SQLException e) {
            throw new EJBException("Database error", e);
        }
        return null;
    }

    private User mapUser(ResultSet rs) throws SQLException {
        User user = new User();
        user.setId(rs.getLong("id"));
        user.setUsername(rs.getString("username"));
        return user;
    }
}
// Fixed: Using JMS for messaging instead of raw sockets
@Stateless
public class FixedNotificationService {

    // Fixed: Use container-managed JMS resources
    @Resource(lookup = "java:/jms/NotificationConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(lookup = "java:/jms/NotificationQueue")
    private Queue notificationQueue;

    // Fixed: Or use injected JMSContext (Java EE 7+)
    @Inject
    @JMSConnectionFactory("java:/jms/NotificationConnectionFactory")
    private JMSContext jmsContext;

    public void sendNotification(String message) {
        // Fixed: Container manages JMS resources
        jmsContext.createProducer()
            .send(notificationQueue, message);
    }
}

// Fixed: Message-driven bean for async processing
@MessageDriven(activationConfig = {
    @ActivationConfigProperty(
        propertyName = "destinationType",
        propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(
        propertyName = "destination",
        propertyValue = "java:/jms/NotificationQueue")
})
public class NotificationProcessor implements MessageListener {

    @Override
    public void onMessage(Message message) {
        // Container manages thread pool for MDBs
        // Security context properly established
        try {
            TextMessage textMessage = (TextMessage) message;
            processNotification(textMessage.getText());
        } catch (JMSException e) {
            throw new EJBException(e);
        }
    }
}
// Fixed: Using dependency injection in ASP.NET Core
public class FixedDataController : ControllerBase
{
    private readonly IDbConnection _connection;
    private readonly IBackgroundTaskQueue _taskQueue;
    private readonly ILogger<FixedDataController> _logger;

    // Fixed: Dependencies injected by container
    public FixedDataController(
        IDbConnection connection,
        IBackgroundTaskQueue taskQueue,
        ILogger<FixedDataController> logger)
    {
        _connection = connection;
        _taskQueue = taskQueue;
        _logger = logger;
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetData(int id, CancellationToken cancellationToken)
    {
        // Fixed: Use injected connection (from pool)
        var data = await _connection.QueryFirstOrDefaultAsync<DataModel>(
            "SELECT * FROM Data WHERE Id = @Id",
            new { Id = id }
        );

        // Fixed: Queue background work properly
        _taskQueue.QueueBackgroundWorkItem(async token =>
        {
            // CancellationToken propagated
            await LogAnalyticsAsync(id, token);
        });

        return Ok(data);
    }
}

// Fixed: Configure services in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    // Fixed: Connection pool managed by DI container
    services.AddScoped<IDbConnection>(sp =>
    {
        var conn = new SqlConnection(Configuration.GetConnectionString("Default"));
        conn.Open();
        return conn;
    });

    // Fixed: Background task queue with hosted service
    services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
    services.AddHostedService<QueuedHostedService>();
}

// Fixed: Background service managed by host
public class QueuedHostedService : BackgroundService
{
    private readonly IBackgroundTaskQueue _taskQueue;
    private readonly ILogger<QueuedHostedService> _logger;

    public QueuedHostedService(
        IBackgroundTaskQueue taskQueue,
        ILogger<QueuedHostedService> logger)
    {
        _taskQueue = taskQueue;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var workItem = await _taskQueue.DequeueAsync(stoppingToken);

            try
            {
                await workItem(stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error executing background work");
            }
        }
    }
}

CVE Examples

This CWE is marked as PROHIBITED for direct CVE mapping as it represents a code quality/design concern rather than a direct security vulnerability.


  • CWE-710: Improper Adherence to Coding Standards (parent)
  • CWE-400: Uncontrolled Resource Consumption (can lead to)
  • CWE-404: Improper Resource Shutdown or Release (related)
  • CWE-1058: Invokable Control Element in Multi-Thread Context (related)

References

  1. MITRE Corporation. "CWE-1065: Runtime Resource Management Control Element in a Component Built to Run on Application Servers." https://cwe.mitre.org/data/definitions/1065.html
  2. Oracle. "Java EE Tutorial - Concurrency Utilities."
  3. Microsoft. "Background tasks with hosted services in ASP.NET Core."