A Serverless Security Library for Developers. Regain Control Over Your AWS Lambda & Google Cloud Functions Runtimes.
We appreciate all the great feedback that we got from the community as part of this project. We've incorporated it into our commercial product, Prisma Cloud. FunctionShield itself is no longer being maintained and we do not recommend using it for production scenarios. This repo continues to be available as a reference only.
A Serverless Security Library for Developers. Regain Control Over Your AWS Lambda & Google Cloud Functions Runtimes.
Created & maintained by PureSec
FunctionShield is a 100% free AWS Lambda security and Google Cloud Functions security library that equips developers with the ability to easily enforce strict security controls on serverless runtimes by addressing 4 common use cases:
In addition to the security protections provided, developers also gain tremendous security visibility when using FunctionShield, even if it's just set to "alert". With FunctionShield deployed in your functions, you can quickly get an idea of what your function is executing, who it is communicating with, and whether or not it is writing to disk.
There have been numerous cases in recent years where malicious actors created bogus software packages that look authentic, or infected existing open source packages with code that leaks sensitive data such as credentials or environment variables. According to a recent survey of 16,000 developers by NPM inc. - 77% of the respondents were concerned with the security of open source software packages. Some organizations have responded to this threat by isolating sensitive serverless functions inside a Virtual Private Cloud (VPC) and using a NAT gateway to monitor/restrict outbound traffic. However, this VPC-based solution presents its own technical challenges.
FunctionShield uses a proprietary behavioral-based runtime protection engine, which enforces the behavior that you define. FunctionShield lives in and around the serverless language runtime. All you have to do is import the library into your code. No function wrapping required. FunctionShield doesn't wrap your code, or perform any kind of monkey-patching.
Below is a sample code snippet, demonstrating how to use FunctionShield:
var AWS = require('aws-sdk');
const FunctionShield = require('@puresec/function-shield');
FunctionShield.configure({
policy: {
// 'block' mode => active blocking
// 'alert' mode => log only
// 'allow' mode => allowed, implicitly occurs if key does not exist
outbound_connectivity: "block",
read_write_tmp: "block",
create_child_process: "block",
read_handler: "block" },
token: process.env.FUNCTION_SHIELD_TOKEN });
exports.hello = async (event) => {
// ... // your code
};
import boto3
import function_shield
function_shield.configure({
"policy": {
# 'block' mode => active blocking
# 'alert' mode => log only
# 'allow' mode => allowed, implicitly occurs if key does not exist
"outbound_connectivity": "block",
"read_write_tmp": "block",
"create_child_process": "block",
"read_handler": "block"
},
"token": os.environ['FUNCTION_SHIELD_TOKEN']
})
def handler(event, context):
# Your Code Here #
package com.serverless;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import org.json.JSONObject;
import io.puresec.FunctionShield;
public class Handler implements RequestHandler <Map <String, Object> , String >
{
static
{
/* 'block' mode => active blocking */
/* 'alert' mode => log only */
/* 'allow' mode => allowed, implicitly occurs if key does not exist */
FunctionShield.configure(new JSONObject()
.put("policy", new JSONObject()
.put("read_write_tmp", "alert")
.put("create_child_process", "alert")
.put("outbound_connectivity", "block")
.put("read_handler", "block"))
.put("token", System.getenv("FUNCTION_SHIELD_TOKEN")));
}
@Override
public String handleRequest(Map <String, Object> input, Context context)
{
/* TODO: Your function code here */
return("Done!");
}
}
'use strict';
const FunctionShield = require('@puresec/function-shield');
FunctionShield.configure(
{
policy: {
// 'block' mode => active blocking
// 'alert' mode => log only
// 'allow' mode => allowed, implicitly occurs if key does not exist
read_write_tmp: "alert",
create_child_process: "alert",
outbound_connectivity: "alert",
read_handler: "alert"
},
disable_analytics: false,
token: process.env.FUNCTION_SHIELD_TOKEN
});
function handler(request, response) {
// ... your code ... //
}
import function_shield
function_shield.configure({
"policy": {
# 'block' mode => active blocking
# 'alert' mode => log only
# 'allow' mode => allowed, implicitly occurs if key does not exist
"read_write_tmp": "block",
"create_child_process": "block",
"outbound_connectivity": "block",
"read_handler": "block"
},
"disable_analytics": False,
"token": os.environ['FUNCTION_SHIELD_TOKEN']
})
def python37_handler(request):
# ... your code here ... #
At the moment, FunctionShield is offered with the following runtimes support:
FunctionShield is also provided as a middleware for the (MIDDY.JS)[https://github.com/middyjs/middy/blob/master/docs/middlewares.md#functionshield] engine.
FunctionShield logs are sent directly to your function's AWS CloudWatch log group or Google cloud logs. Here are a few sample logs, demonstrating the log format you should expect:
// Log example #1:
{
"function_shield": true,
"policy": "outbound_connectivity",
"details": {
"host": "google.com"
},
"mode": "alert"
}
// Log example #2:
{
"function_shield": true,
"policy": "read_write_tmp",
"details": {
"path": "/tmp/node-alert"
},
"mode": "alert"
}
// Log example #3:
{
"function_shield": true,
"policy": "create_child_process",
"details": {
"path": "/bin/sh"
},
"mode": "block"
}
// Log example #4:
{
"function_shield": true,
"policy": "read_handler",
"details": {
"path": "/var/task/handler.js"
},
"mode": "alert"
}
If you want to test FunctionShield, we have prepared some code snippets, which you can use to force triggers:
[![FunctionShieldInside](https://www.puresec.io/hubfs/fshield-badge.svg)](https://www.puresec.io/function-shield)
Creative Commons Attribution No Derivatives 4.0 International
Special thanks to Tomer Zait (@realgam3) for discovering an issue that allows bypass of "read_write_tmp" blocking functionality. This problem is corrected in the final build of FunctionShield.